summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Basic
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2017-01-14 19:55:43 +0000
committerpatrick <patrick@openbsd.org>2017-01-14 19:55:43 +0000
commitbd3306aecb3a15e8967143b8cdbbccf2b1b19b74 (patch)
tree309a8132b44564b9e634c0da6815187ce8eab27c /gnu/llvm/tools/clang/lib/Basic
parentkillp -a should not kill the window if only one pane. (diff)
downloadwireguard-openbsd-bd3306aecb3a15e8967143b8cdbbccf2b1b19b74.tar.xz
wireguard-openbsd-bd3306aecb3a15e8967143b8cdbbccf2b1b19b74.zip
Import LLVM 3.9.1 including clang and lld.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Basic')
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/Builtins.cpp4
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/CMakeLists.txt8
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/Cuda.cpp171
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/Diagnostic.cpp1
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp8
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/FileManager.cpp10
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/IdentifierTable.cpp1
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/LangOptions.cpp1
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/Module.cpp11
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp203
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp1
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/SourceManager.cpp45
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/TargetInfo.cpp12
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/Version.cpp2
-rw-r--r--gnu/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp363
15 files changed, 734 insertions, 107 deletions
diff --git a/gnu/llvm/tools/clang/lib/Basic/Builtins.cpp b/gnu/llvm/tools/clang/lib/Basic/Builtins.cpp
index fb6a6451aa8..28695d649a8 100644
--- a/gnu/llvm/tools/clang/lib/Basic/Builtins.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/Builtins.cpp
@@ -69,7 +69,9 @@ bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
bool MSModeUnsupported =
!LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);
bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG;
- return !BuiltinsUnsupported && !MathBuiltinsUnsupported &&
+ bool OclCUnsupported = LangOpts.OpenCLVersion != 200 &&
+ BuiltinInfo.Langs == OCLC20_LANG;
+ return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported &&
!GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported;
}
diff --git a/gnu/llvm/tools/clang/lib/Basic/CMakeLists.txt b/gnu/llvm/tools/clang/lib/Basic/CMakeLists.txt
index cfad8c3649e..ad460d49653 100644
--- a/gnu/llvm/tools/clang/lib/Basic/CMakeLists.txt
+++ b/gnu/llvm/tools/clang/lib/Basic/CMakeLists.txt
@@ -53,12 +53,20 @@ if(DEFINED llvm_vc AND DEFINED clang_vc)
else()
# Not producing a VC revision include.
set(version_inc)
+
+ # Being able to force-set the SVN revision in cases where it isn't available
+ # is useful for performance tracking, and matches compatibility from autoconf.
+ if(SVN_REVISION)
+ set_source_files_properties(Version.cpp
+ PROPERTIES COMPILE_DEFINITIONS "SVN_REVISION=\"${SVN_REVISION}\"")
+ endif()
endif()
add_clang_library(clangBasic
Attributes.cpp
Builtins.cpp
CharInfo.cpp
+ Cuda.cpp
Diagnostic.cpp
DiagnosticIDs.cpp
DiagnosticOptions.cpp
diff --git a/gnu/llvm/tools/clang/lib/Basic/Cuda.cpp b/gnu/llvm/tools/clang/lib/Basic/Cuda.cpp
new file mode 100644
index 00000000000..3264078b98f
--- /dev/null
+++ b/gnu/llvm/tools/clang/lib/Basic/Cuda.cpp
@@ -0,0 +1,171 @@
+#include "clang/Basic/Cuda.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+
+const char *CudaVersionToString(CudaVersion V) {
+ switch (V) {
+ case CudaVersion::UNKNOWN:
+ return "unknown";
+ case CudaVersion::CUDA_70:
+ return "7.0";
+ case CudaVersion::CUDA_75:
+ return "7.5";
+ case CudaVersion::CUDA_80:
+ return "8.0";
+ }
+ llvm_unreachable("invalid enum");
+}
+
+const char *CudaArchToString(CudaArch A) {
+ switch (A) {
+ case CudaArch::UNKNOWN:
+ return "unknown";
+ case CudaArch::SM_20:
+ return "sm_20";
+ case CudaArch::SM_21:
+ return "sm_21";
+ case CudaArch::SM_30:
+ return "sm_30";
+ case CudaArch::SM_32:
+ return "sm_32";
+ case CudaArch::SM_35:
+ return "sm_35";
+ case CudaArch::SM_37:
+ return "sm_37";
+ case CudaArch::SM_50:
+ return "sm_50";
+ case CudaArch::SM_52:
+ return "sm_52";
+ case CudaArch::SM_53:
+ return "sm_53";
+ case CudaArch::SM_60:
+ return "sm_60";
+ case CudaArch::SM_61:
+ return "sm_61";
+ case CudaArch::SM_62:
+ return "sm_62";
+ }
+ llvm_unreachable("invalid enum");
+}
+
+CudaArch StringToCudaArch(llvm::StringRef S) {
+ return llvm::StringSwitch<CudaArch>(S)
+ .Case("sm_20", CudaArch::SM_20)
+ .Case("sm_21", CudaArch::SM_21)
+ .Case("sm_30", CudaArch::SM_30)
+ .Case("sm_32", CudaArch::SM_32)
+ .Case("sm_35", CudaArch::SM_35)
+ .Case("sm_37", CudaArch::SM_37)
+ .Case("sm_50", CudaArch::SM_50)
+ .Case("sm_52", CudaArch::SM_52)
+ .Case("sm_53", CudaArch::SM_53)
+ .Case("sm_60", CudaArch::SM_60)
+ .Case("sm_61", CudaArch::SM_61)
+ .Case("sm_62", CudaArch::SM_62)
+ .Default(CudaArch::UNKNOWN);
+}
+
+const char *CudaVirtualArchToString(CudaVirtualArch A) {
+ switch (A) {
+ case CudaVirtualArch::UNKNOWN:
+ return "unknown";
+ case CudaVirtualArch::COMPUTE_20:
+ return "compute_20";
+ case CudaVirtualArch::COMPUTE_30:
+ return "compute_30";
+ case CudaVirtualArch::COMPUTE_32:
+ return "compute_32";
+ case CudaVirtualArch::COMPUTE_35:
+ return "compute_35";
+ case CudaVirtualArch::COMPUTE_37:
+ return "compute_37";
+ case CudaVirtualArch::COMPUTE_50:
+ return "compute_50";
+ case CudaVirtualArch::COMPUTE_52:
+ return "compute_52";
+ case CudaVirtualArch::COMPUTE_53:
+ return "compute_53";
+ case CudaVirtualArch::COMPUTE_60:
+ return "compute_60";
+ case CudaVirtualArch::COMPUTE_61:
+ return "compute_61";
+ case CudaVirtualArch::COMPUTE_62:
+ return "compute_62";
+ }
+ llvm_unreachable("invalid enum");
+}
+
+CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S) {
+ return llvm::StringSwitch<CudaVirtualArch>(S)
+ .Case("compute_20", CudaVirtualArch::COMPUTE_20)
+ .Case("compute_30", CudaVirtualArch::COMPUTE_30)
+ .Case("compute_32", CudaVirtualArch::COMPUTE_32)
+ .Case("compute_35", CudaVirtualArch::COMPUTE_35)
+ .Case("compute_37", CudaVirtualArch::COMPUTE_37)
+ .Case("compute_50", CudaVirtualArch::COMPUTE_50)
+ .Case("compute_52", CudaVirtualArch::COMPUTE_52)
+ .Case("compute_53", CudaVirtualArch::COMPUTE_53)
+ .Case("compute_60", CudaVirtualArch::COMPUTE_60)
+ .Case("compute_61", CudaVirtualArch::COMPUTE_61)
+ .Case("compute_62", CudaVirtualArch::COMPUTE_62)
+ .Default(CudaVirtualArch::UNKNOWN);
+}
+
+CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
+ switch (A) {
+ case CudaArch::UNKNOWN:
+ return CudaVirtualArch::UNKNOWN;
+ case CudaArch::SM_20:
+ case CudaArch::SM_21:
+ return CudaVirtualArch::COMPUTE_20;
+ case CudaArch::SM_30:
+ return CudaVirtualArch::COMPUTE_30;
+ case CudaArch::SM_32:
+ return CudaVirtualArch::COMPUTE_32;
+ case CudaArch::SM_35:
+ return CudaVirtualArch::COMPUTE_35;
+ case CudaArch::SM_37:
+ return CudaVirtualArch::COMPUTE_37;
+ case CudaArch::SM_50:
+ return CudaVirtualArch::COMPUTE_50;
+ case CudaArch::SM_52:
+ return CudaVirtualArch::COMPUTE_52;
+ case CudaArch::SM_53:
+ return CudaVirtualArch::COMPUTE_53;
+ case CudaArch::SM_60:
+ return CudaVirtualArch::COMPUTE_60;
+ case CudaArch::SM_61:
+ return CudaVirtualArch::COMPUTE_61;
+ case CudaArch::SM_62:
+ return CudaVirtualArch::COMPUTE_62;
+ }
+ llvm_unreachable("invalid enum");
+}
+
+CudaVersion MinVersionForCudaArch(CudaArch A) {
+ switch (A) {
+ case CudaArch::UNKNOWN:
+ return CudaVersion::UNKNOWN;
+ case CudaArch::SM_20:
+ case CudaArch::SM_21:
+ case CudaArch::SM_30:
+ case CudaArch::SM_32:
+ case CudaArch::SM_35:
+ case CudaArch::SM_37:
+ case CudaArch::SM_50:
+ case CudaArch::SM_52:
+ case CudaArch::SM_53:
+ return CudaVersion::CUDA_70;
+ case CudaArch::SM_60:
+ case CudaArch::SM_61:
+ case CudaArch::SM_62:
+ return CudaVersion::CUDA_80;
+ }
+ llvm_unreachable("invalid enum");
+}
+
+} // namespace clang
diff --git a/gnu/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/gnu/llvm/tools/clang/lib/Basic/Diagnostic.cpp
index 7cf7305827f..f10d156743b 100644
--- a/gnu/llvm/tools/clang/lib/Basic/Diagnostic.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/Diagnostic.cpp
@@ -68,6 +68,7 @@ DiagnosticsEngine::DiagnosticsEngine(
WarningsAsErrors = false;
EnableAllWarnings = false;
ErrorsAsFatal = false;
+ FatalsAsError = false;
SuppressSystemWarnings = false;
SuppressAllDiagnostics = false;
ElideType = true;
diff --git a/gnu/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/gnu/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
index a34c7fecb53..3c370f67fa3 100644
--- a/gnu/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -351,7 +351,7 @@ bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
if (DiagID >= diag::DIAG_UPPER_LIMIT)
return false;
- return GetDefaultDiagMapping(DiagID).getSeverity() == diag::Severity::Error;
+ return GetDefaultDiagMapping(DiagID).getSeverity() >= diag::Severity::Error;
}
/// getDescription - Given a diagnostic ID, return a description of the
@@ -462,6 +462,12 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
Result = diag::Severity::Fatal;
}
+ // If explicitly requested, map fatal errors to errors.
+ if (Result == diag::Severity::Fatal) {
+ if (Diag.FatalsAsError)
+ Result = diag::Severity::Error;
+ }
+
// Custom diagnostics always are emitted in system headers.
bool ShowInSystemHeader =
!GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
diff --git a/gnu/llvm/tools/clang/lib/Basic/FileManager.cpp b/gnu/llvm/tools/clang/lib/Basic/FileManager.cpp
index cb3f75c25a0..ce9b7e1bb48 100644
--- a/gnu/llvm/tools/clang/lib/Basic/FileManager.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/FileManager.cpp
@@ -19,7 +19,6 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ADT/STLExtras.h"
@@ -124,7 +123,7 @@ static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
StringRef DirName = llvm::sys::path::parent_path(Path);
if (DirName.empty())
- return;
+ DirName = ".";
auto &NamedDirEnt =
*SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first;
@@ -313,6 +312,9 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
UFE.InPCH = Data.InPCH;
UFE.File = std::move(F);
UFE.IsValid = true;
+ if (UFE.File)
+ if (auto RealPathName = UFE.File->getName())
+ UFE.RealPathName = *RealPathName;
return &UFE;
}
@@ -564,7 +566,3 @@ void FileManager::PrintStats() const {
//llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
}
-
-// Virtual destructors for abstract base classes that need live in Basic.
-PCHContainerWriter::~PCHContainerWriter() {}
-PCHContainerReader::~PCHContainerReader() {}
diff --git a/gnu/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/gnu/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
index 67de1cb6fda..d6ad0f5c915 100644
--- a/gnu/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
@@ -42,6 +42,7 @@ IdentifierInfo::IdentifierInfo() {
NeedsHandleIdentifier = false;
IsFromAST = false;
ChangedAfterLoad = false;
+ FEChangedAfterLoad = false;
RevertedTokenID = false;
OutOfDate = false;
IsModulesImport = false;
diff --git a/gnu/llvm/tools/clang/lib/Basic/LangOptions.cpp b/gnu/llvm/tools/clang/lib/Basic/LangOptions.cpp
index 1b08b068604..8c0ecd46ad5 100644
--- a/gnu/llvm/tools/clang/lib/Basic/LangOptions.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/LangOptions.cpp
@@ -34,7 +34,6 @@ void LangOptions::resetNonModularOptions() {
SanitizerBlacklistFiles.clear();
CurrentModule.clear();
- ImplementationOfModule.clear();
}
bool LangOptions::isNoBuiltinFunc(const char *Name) const {
diff --git a/gnu/llvm/tools/clang/lib/Basic/Module.cpp b/gnu/llvm/tools/clang/lib/Basic/Module.cpp
index 0b783263694..3d1a40db5ea 100644
--- a/gnu/llvm/tools/clang/lib/Basic/Module.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/Module.cpp
@@ -418,12 +418,8 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS.indent(Indent + 2);
OS << "export ";
printModuleId(OS, UnresolvedExports[I].Id);
- if (UnresolvedExports[I].Wildcard) {
- if (UnresolvedExports[I].Id.empty())
- OS << "*";
- else
- OS << ".*";
- }
+ if (UnresolvedExports[I].Wildcard)
+ OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*");
OS << "\n";
}
@@ -486,12 +482,13 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS << "}\n";
}
-void Module::dump() const {
+LLVM_DUMP_METHOD void Module::dump() const {
print(llvm::errs());
}
void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
VisibleCallback Vis, ConflictCallback Cb) {
+ assert(Loc.isValid() && "setVisible expects a valid import location");
if (isVisible(M))
return;
diff --git a/gnu/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp b/gnu/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
index 577132dc144..d1e4779e2c7 100644
--- a/gnu/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
@@ -55,6 +55,7 @@ OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) {
return llvm::StringSwitch<OpenMPClauseKind>(Str)
#define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name)
#include "clang/Basic/OpenMPKinds.def"
+ .Case("uniform", OMPC_uniform)
.Default(OMPC_unknown);
}
@@ -67,6 +68,8 @@ const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) {
case OMPC_##Name: \
return #Name;
#include "clang/Basic/OpenMPKinds.def"
+ case OMPC_uniform:
+ return "uniform";
case OMPC_threadprivate:
return "threadprivate or thread local";
}
@@ -109,6 +112,19 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
#define OPENMP_MAP_KIND(Name) .Case(#Name, OMPC_MAP_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_MAP_unknown);
+ case OMPC_dist_schedule:
+ return llvm::StringSwitch<OpenMPDistScheduleClauseKind>(Str)
+#define OPENMP_DIST_SCHEDULE_KIND(Name) .Case(#Name, OMPC_DIST_SCHEDULE_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DIST_SCHEDULE_unknown);
+ case OMPC_defaultmap:
+ return llvm::StringSwitch<unsigned>(Str)
+#define OPENMP_DEFAULTMAP_KIND(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_DEFAULTMAP_##Name))
+#define OPENMP_DEFAULTMAP_MODIFIER(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_DEFAULTMAP_MODIFIER_##Name))
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DEFAULTMAP_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@@ -145,6 +161,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
+ case OMPC_uniform:
+ case OMPC_to:
+ case OMPC_from:
+ case OMPC_use_device_ptr:
+ case OMPC_is_device_ptr:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -219,6 +240,30 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
break;
}
llvm_unreachable("Invalid OpenMP 'map' clause type");
+ case OMPC_dist_schedule:
+ switch (Type) {
+ case OMPC_DIST_SCHEDULE_unknown:
+ return "unknown";
+#define OPENMP_DIST_SCHEDULE_KIND(Name) \
+ case OMPC_DIST_SCHEDULE_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'dist_schedule' clause type");
+ case OMPC_defaultmap:
+ switch (Type) {
+ case OMPC_DEFAULTMAP_unknown:
+ case OMPC_DEFAULTMAP_MODIFIER_last:
+ return "unknown";
+#define OPENMP_DEFAULTMAP_KIND(Name) \
+ case OMPC_DEFAULTMAP_##Name: \
+ return #Name;
+#define OPENMP_DEFAULTMAP_MODIFIER(Name) \
+ case OMPC_DEFAULTMAP_MODIFIER_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'schedule' clause type");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@@ -255,6 +300,11 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
+ case OMPC_uniform:
+ case OMPC_to:
+ case OMPC_from:
+ case OMPC_use_device_ptr:
+ case OMPC_is_device_ptr:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -398,6 +448,56 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_target_enter_data:
+ switch (CKind) {
+#define OPENMP_TARGET_ENTER_DATA_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_exit_data:
+ switch (CKind) {
+#define OPENMP_TARGET_EXIT_DATA_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_parallel:
+ switch (CKind) {
+#define OPENMP_TARGET_PARALLEL_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_parallel_for:
+ switch (CKind) {
+#define OPENMP_TARGET_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_update:
+ switch (CKind) {
+#define OPENMP_TARGET_UPDATE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
case OMPD_teams:
switch (CKind) {
#define OPENMP_TEAMS_CLAUSE(Name) \
@@ -408,6 +508,8 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_declare_simd:
+ break;
case OMPD_cancel:
switch (CKind) {
#define OPENMP_CANCEL_CLAUSE(Name) \
@@ -468,6 +570,48 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_distribute_parallel_for:
+ switch (CKind) {
+#define OPENMP_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_distribute_parallel_for_simd:
+ switch (CKind) {
+#define OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_distribute_simd:
+ switch (CKind) {
+#define OPENMP_DISTRIBUTE_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_parallel_for_simd:
+ switch (CKind) {
+#define OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
case OMPD_unknown:
case OMPD_threadprivate:
case OMPD_section:
@@ -477,6 +621,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
case OMPD_taskwait:
case OMPD_taskgroup:
case OMPD_cancellation_point:
+ case OMPD_declare_reduction:
break;
}
return false;
@@ -485,17 +630,25 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_simd || DKind == OMPD_for || DKind == OMPD_for_simd ||
DKind == OMPD_parallel_for || DKind == OMPD_parallel_for_simd ||
- DKind == OMPD_taskloop ||
- DKind == OMPD_taskloop_simd ||
- DKind == OMPD_distribute; // TODO add next directives.
+ DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd ||
+ DKind == OMPD_distribute || DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_distribute_parallel_for ||
+ DKind == OMPD_distribute_parallel_for_simd ||
+ DKind == OMPD_distribute_simd ||
+ DKind == OMPD_target_parallel_for_simd;
+ // TODO add next directives.
}
bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_for || DKind == OMPD_for_simd ||
DKind == OMPD_sections || DKind == OMPD_section ||
DKind == OMPD_single || DKind == OMPD_parallel_for ||
- DKind == OMPD_parallel_for_simd ||
- DKind == OMPD_parallel_sections; // TODO add next directives.
+ DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections ||
+ DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_distribute_parallel_for ||
+ DKind == OMPD_distribute_parallel_for_simd ||
+ DKind == OMPD_target_parallel_for_simd;
+ // TODO add next directives.
}
bool clang::isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind) {
@@ -504,12 +657,24 @@ bool clang::isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind) {
bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_parallel || DKind == OMPD_parallel_for ||
- DKind == OMPD_parallel_for_simd ||
- DKind == OMPD_parallel_sections; // TODO add next directives.
+ DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections ||
+ DKind == OMPD_target_parallel || DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_distribute_parallel_for ||
+ DKind == OMPD_distribute_parallel_for_simd ||
+ DKind == OMPD_target_parallel_for_simd;
+ // TODO add next directives.
}
-bool clang::isOpenMPTargetDirective(OpenMPDirectiveKind DKind) {
- return DKind == OMPD_target; // TODO add next directives.
+bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
+ // TODO add next directives.
+ return DKind == OMPD_target || DKind == OMPD_target_parallel ||
+ DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_target_parallel_for_simd;
+}
+
+bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_target_data || DKind == OMPD_target_enter_data ||
+ DKind == OMPD_target_exit_data || DKind == OMPD_target_update;
}
bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
@@ -518,12 +683,17 @@ bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_simd || DKind == OMPD_for_simd ||
- DKind == OMPD_parallel_for_simd ||
- DKind == OMPD_taskloop_simd; // TODO add next directives.
+ DKind == OMPD_parallel_for_simd || DKind == OMPD_taskloop_simd ||
+ DKind == OMPD_distribute_parallel_for_simd ||
+ DKind == OMPD_distribute_simd;
+ // TODO add next directives.
}
bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
- return Kind == OMPD_distribute; // TODO add next directives.
+ return Kind == OMPD_distribute || Kind == OMPD_distribute_parallel_for ||
+ Kind == OMPD_distribute_parallel_for_simd ||
+ Kind == OMPD_distribute_simd;
+ // TODO add next directives.
}
bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
@@ -536,3 +706,12 @@ bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) {
return Kind == OMPC_threadprivate || Kind == OMPC_copyin;
}
+bool clang::isOpenMPTaskingDirective(OpenMPDirectiveKind Kind) {
+ return Kind == OMPD_task || isOpenMPTaskLoopDirective(Kind);
+}
+
+bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) {
+ return Kind == OMPD_distribute_parallel_for ||
+ Kind == OMPD_distribute_parallel_for_simd ||
+ Kind == OMPD_distribute_simd;
+}
diff --git a/gnu/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp b/gnu/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
index ade8d6d841d..384d23c38af 100644
--- a/gnu/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
@@ -53,6 +53,7 @@ prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator,
case tok::pipeequal: return prec::Assignment;
case tok::question: return prec::Conditional;
case tok::pipepipe: return prec::LogicalOr;
+ case tok::caretcaret:
case tok::ampamp: return prec::LogicalAnd;
case tok::pipe: return prec::InclusiveOr;
case tok::caret: return prec::ExclusiveOr;
diff --git a/gnu/llvm/tools/clang/lib/Basic/SourceManager.cpp b/gnu/llvm/tools/clang/lib/Basic/SourceManager.cpp
index 4c501616a3e..1e83b63cf82 100644
--- a/gnu/llvm/tools/clang/lib/Basic/SourceManager.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -1160,7 +1160,8 @@ unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
// isInvalid - Return the result of calling loc.isInvalid(), and
// if Invalid is not null, set its value to same.
-static bool isInvalid(SourceLocation Loc, bool *Invalid) {
+template<typename LocType>
+static bool isInvalid(LocType Loc, bool *Invalid) {
bool MyInvalid = Loc.isInvalid();
if (Invalid)
*Invalid = MyInvalid;
@@ -1183,8 +1184,9 @@ unsigned SourceManager::getExpansionColumnNumber(SourceLocation Loc,
unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc,
bool *Invalid) const {
- if (isInvalid(Loc, Invalid)) return 0;
- return getPresumedLoc(Loc).getColumn();
+ PresumedLoc PLoc = getPresumedLoc(Loc);
+ if (isInvalid(PLoc, Invalid)) return 0;
+ return PLoc.getColumn();
}
#ifdef __SSE2__
@@ -1258,15 +1260,19 @@ FoundSpecialChar:
if (Buf[0] == '\n' || Buf[0] == '\r') {
// If this is \n\r or \r\n, skip both characters.
- if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
- ++Offs, ++Buf;
- ++Offs, ++Buf;
+ if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1]) {
+ ++Offs;
+ ++Buf;
+ }
+ ++Offs;
+ ++Buf;
LineOffsets.push_back(Offs);
} else {
// Otherwise, this is a null. If end of file, exit.
if (Buf == End) break;
// Otherwise, skip the null.
- ++Offs, ++Buf;
+ ++Offs;
+ ++Buf;
}
}
@@ -1388,8 +1394,9 @@ unsigned SourceManager::getExpansionLineNumber(SourceLocation Loc,
}
unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc,
bool *Invalid) const {
- if (isInvalid(Loc, Invalid)) return 0;
- return getPresumedLoc(Loc).getLine();
+ PresumedLoc PLoc = getPresumedLoc(Loc);
+ if (isInvalid(PLoc, Invalid)) return 0;
+ return PLoc.getLine();
}
/// getFileCharacteristic - return the file characteristic of the specified
@@ -2089,10 +2096,10 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
// Clear the lookup cache, it depends on a common location.
IsBeforeInTUCache.clear();
- llvm::MemoryBuffer *LBuf = getBuffer(LOffs.first);
- llvm::MemoryBuffer *RBuf = getBuffer(ROffs.first);
- bool LIsBuiltins = strcmp("<built-in>", LBuf->getBufferIdentifier()) == 0;
- bool RIsBuiltins = strcmp("<built-in>", RBuf->getBufferIdentifier()) == 0;
+ const char *LB = getBuffer(LOffs.first)->getBufferIdentifier();
+ const char *RB = getBuffer(ROffs.first)->getBufferIdentifier();
+ bool LIsBuiltins = strcmp("<built-in>", LB) == 0;
+ bool RIsBuiltins = strcmp("<built-in>", RB) == 0;
// Sort built-in before non-built-in.
if (LIsBuiltins || RIsBuiltins) {
if (LIsBuiltins != RIsBuiltins)
@@ -2101,8 +2108,8 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
// lower IDs come first.
return LOffs.first < ROffs.first;
}
- bool LIsAsm = strcmp("<inline asm>", LBuf->getBufferIdentifier()) == 0;
- bool RIsAsm = strcmp("<inline asm>", RBuf->getBufferIdentifier()) == 0;
+ bool LIsAsm = strcmp("<inline asm>", LB) == 0;
+ bool RIsAsm = strcmp("<inline asm>", RB) == 0;
// Sort assembler after built-ins, but before the rest.
if (LIsAsm || RIsAsm) {
if (LIsAsm != RIsAsm)
@@ -2110,6 +2117,14 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
assert(LOffs.first == ROffs.first);
return false;
}
+ bool LIsScratch = strcmp("<scratch space>", LB) == 0;
+ bool RIsScratch = strcmp("<scratch space>", RB) == 0;
+ // Sort scratch after inline asm, but before the rest.
+ if (LIsScratch || RIsScratch) {
+ if (LIsScratch != RIsScratch)
+ return LIsScratch;
+ return LOffs.second < ROffs.second;
+ }
llvm_unreachable("Unsortable locations found");
}
diff --git a/gnu/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/gnu/llvm/tools/clang/lib/Basic/TargetInfo.cpp
index 1648a27d8b3..92f658a6a37 100644
--- a/gnu/llvm/tools/clang/lib/Basic/TargetInfo.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/TargetInfo.cpp
@@ -30,6 +30,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
BigEndian = true;
TLSSupported = true;
NoAsmVariants = false;
+ HasFloat128 = false;
PointerWidth = PointerAlign = 32;
BoolWidth = BoolAlign = 8;
IntWidth = IntAlign = 32;
@@ -46,6 +47,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
DoubleAlign = 64;
LongDoubleWidth = 64;
LongDoubleAlign = 64;
+ Float128Align = 128;
LargeArrayMinWidth = 0;
LargeArrayAlign = 0;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
@@ -66,13 +68,13 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
UseSignedCharForObjCBool = true;
UseBitFieldTypeAlignment = true;
UseZeroLengthBitfieldAlignment = false;
+ UseExplicitBitFieldAlignment = true;
ZeroLengthBitfieldBoundary = 0;
HalfFormat = &llvm::APFloat::IEEEhalf;
FloatFormat = &llvm::APFloat::IEEEsingle;
DoubleFormat = &llvm::APFloat::IEEEdouble;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
- DataLayoutString = nullptr;
- UserLabelPrefix = "_";
+ Float128Format = &llvm::APFloat::IEEEquad;
MCountName = "mcount";
RegParmMax = 0;
SSERegParmMax = 0;
@@ -224,6 +226,8 @@ TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble ||
&getLongDoubleFormat() == &llvm::APFloat::IEEEquad)
return LongDouble;
+ if (hasFloat128Type())
+ return Float128;
break;
}
@@ -276,6 +280,10 @@ void TargetInfo::adjust(const LangOptions &Opts) {
UseBitFieldTypeAlignment = false;
if (Opts.ShortWChar)
WCharType = UnsignedShort;
+ if (Opts.AlignDouble) {
+ DoubleAlign = LongLongAlign = 64;
+ LongDoubleAlign = 64;
+ }
if (Opts.OpenCL) {
// OpenCL C requires specific widths for types, irrespective of
diff --git a/gnu/llvm/tools/clang/lib/Basic/Version.cpp b/gnu/llvm/tools/clang/lib/Basic/Version.cpp
index 58b40cca6fd..4fa52b4acce 100644
--- a/gnu/llvm/tools/clang/lib/Basic/Version.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/Version.cpp
@@ -36,7 +36,7 @@ std::string getClangRepositoryPath() {
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
// pick up a tag in an SVN export, for example.
- StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_381/final/lib/Basic/Version.cpp $");
+ StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_391/final/lib/Basic/Version.cpp $");
if (URL.empty()) {
URL = SVNRepository.slice(SVNRepository.find(':'),
SVNRepository.find("/lib/Basic"));
diff --git a/gnu/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/gnu/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
index 6977f400287..8ace2b3dc83 100644
--- a/gnu/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
@@ -16,13 +16,16 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/YAMLParser.h"
-#include "llvm/Config/llvm-config.h"
#include <atomic>
#include <memory>
+#include <utility>
// For chdir.
#ifdef LLVM_ON_WIN32
@@ -99,6 +102,9 @@ FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
}
std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
+ if (llvm::sys::path::is_absolute(Path))
+ return std::error_code();
+
auto WorkingDir = getCurrentWorkingDirectory();
if (!WorkingDir)
return WorkingDir.getError();
@@ -111,6 +117,20 @@ bool FileSystem::exists(const Twine &Path) {
return Status && Status->exists();
}
+#ifndef NDEBUG
+static bool isTraversalComponent(StringRef Component) {
+ return Component.equals("..") || Component.equals(".");
+}
+
+static bool pathHasTraversal(StringRef Path) {
+ using namespace llvm::sys;
+ for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
+ if (isTraversalComponent(Comp))
+ return true;
+ return false;
+}
+#endif
+
//===-----------------------------------------------------------------------===/
// RealFileSystem implementation
//===-----------------------------------------------------------------------===/
@@ -120,16 +140,19 @@ namespace {
class RealFile : public File {
int FD;
Status S;
+ std::string RealName;
friend class RealFileSystem;
- RealFile(int FD, StringRef NewName)
+ RealFile(int FD, StringRef NewName, StringRef NewRealPathName)
: FD(FD), S(NewName, {}, {}, {}, {}, {},
- llvm::sys::fs::file_type::status_error, {}) {
+ llvm::sys::fs::file_type::status_error, {}),
+ RealName(NewRealPathName.str()) {
assert(FD >= 0 && "Invalid or inactive file descriptor");
}
public:
~RealFile() override;
ErrorOr<Status> status() override;
+ ErrorOr<std::string> getName() override;
ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
int64_t FileSize,
bool RequiresNullTerminator,
@@ -150,6 +173,10 @@ ErrorOr<Status> RealFile::status() {
return S;
}
+ErrorOr<std::string> RealFile::getName() {
+ return RealName.empty() ? S.getName().str() : RealName;
+}
+
ErrorOr<std::unique_ptr<MemoryBuffer>>
RealFile::getBuffer(const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator, bool IsVolatile) {
@@ -158,21 +185,10 @@ RealFile::getBuffer(const Twine &Name, int64_t FileSize,
IsVolatile);
}
-// FIXME: This is terrible, we need this for ::close.
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#include <sys/uio.h>
-#else
-#include <io.h>
-#ifndef S_ISFIFO
-#define S_ISFIFO(x) (0)
-#endif
-#endif
std::error_code RealFile::close() {
- if (::close(FD))
- return std::error_code(errno, std::generic_category());
+ std::error_code EC = sys::Process::SafelyCloseFileDescriptor(FD);
FD = -1;
- return std::error_code();
+ return EC;
}
namespace {
@@ -198,9 +214,10 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
ErrorOr<std::unique_ptr<File>>
RealFileSystem::openFileForRead(const Twine &Name) {
int FD;
- if (std::error_code EC = sys::fs::openFileForRead(Name, FD))
+ SmallString<256> RealName;
+ if (std::error_code EC = sys::fs::openFileForRead(Name, FD, &RealName))
return EC;
- return std::unique_ptr<File>(new RealFile(FD, Name.str()));
+ return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str()));
}
llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
@@ -271,7 +288,7 @@ directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
// OverlayFileSystem implementation
//===-----------------------------------------------------------------------===/
OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
- FSList.push_back(BaseFS);
+ FSList.push_back(std::move(BaseFS));
}
void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) {
@@ -711,7 +728,13 @@ public:
Status S)
: Entry(EK_Directory, Name), Contents(std::move(Contents)),
S(std::move(S)) {}
+ RedirectingDirectoryEntry(StringRef Name, Status S)
+ : Entry(EK_Directory, Name), S(std::move(S)) {}
Status getStatus() { return S; }
+ void addContent(std::unique_ptr<Entry> Content) {
+ Contents.push_back(std::move(Content));
+ }
+ Entry *getLastContent() const { return Contents.back().get(); }
typedef decltype(Contents)::iterator iterator;
iterator contents_begin() { return Contents.begin(); }
iterator contents_end() { return Contents.end(); }
@@ -739,6 +762,7 @@ public:
return UseName == NK_NotSet ? GlobalUseExternalName
: (UseName == NK_External);
}
+ NameKind getUseName() const { return UseName; }
static bool classof(const Entry *E) { return E->getKind() == EK_File; }
};
@@ -776,6 +800,7 @@ public:
/// All configuration options are optional.
/// 'case-sensitive': <boolean, default=true>
/// 'use-external-names': <boolean, default=true>
+/// 'overlay-relative': <boolean, default=false>
///
/// Virtual directories are represented as
/// \verbatim
@@ -815,6 +840,10 @@ class RedirectingFileSystem : public vfs::FileSystem {
std::vector<std::unique_ptr<Entry>> Roots;
/// \brief The file system to use for external references.
IntrusiveRefCntPtr<FileSystem> ExternalFS;
+ /// If IsRelativeOverlay is set, this represents the directory
+ /// path that should be prefixed to each 'external-contents' entry
+ /// when reading from YAML files.
+ std::string ExternalContentsPrefixDir;
/// @name Configuration
/// @{
@@ -822,18 +851,32 @@ class RedirectingFileSystem : public vfs::FileSystem {
/// \brief Whether to perform case-sensitive comparisons.
///
/// Currently, case-insensitive matching only works correctly with ASCII.
- bool CaseSensitive;
+ bool CaseSensitive = true;
+
+ /// IsRelativeOverlay marks whether a IsExternalContentsPrefixDir path must
+ /// be prefixed in every 'external-contents' when reading from YAML files.
+ bool IsRelativeOverlay = false;
/// \brief Whether to use to use the value of 'external-contents' for the
/// names of files. This global value is overridable on a per-file basis.
- bool UseExternalNames;
+ bool UseExternalNames = true;
/// @}
+ /// Virtual file paths and external files could be canonicalized without "..",
+ /// "." and "./" in their paths. FIXME: some unittests currently fail on
+ /// win32 when using remove_dots and remove_leading_dotslash on paths.
+ bool UseCanonicalizedPaths =
+#ifdef LLVM_ON_WIN32
+ false;
+#else
+ true;
+#endif
+
friend class RedirectingFileSystemParser;
private:
RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
- : ExternalFS(ExternalFS), CaseSensitive(true), UseExternalNames(true) {}
+ : ExternalFS(std::move(ExternalFS)) {}
/// \brief Looks up \p Path in \c Roots.
ErrorOr<Entry *> lookupPath(const Twine &Path);
@@ -851,8 +894,8 @@ public:
/// returns a virtual file system representing its contents.
static RedirectingFileSystem *
create(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS);
+ SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
+ void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
ErrorOr<Status> status(const Twine &Path) override;
ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
@@ -885,6 +928,38 @@ public:
return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(Dir,
*this, D->contents_begin(), D->contents_end(), EC));
}
+
+ void setExternalContentsPrefixDir(StringRef PrefixDir) {
+ ExternalContentsPrefixDir = PrefixDir.str();
+ }
+
+ StringRef getExternalContentsPrefixDir() const {
+ return ExternalContentsPrefixDir;
+ }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void dump() const {
+ for (const std::unique_ptr<Entry> &Root : Roots)
+ dumpEntry(Root.get());
+ }
+
+LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const {
+ StringRef Name = E->getName();
+ for (int i = 0, e = NumSpaces; i < e; ++i)
+ dbgs() << " ";
+ dbgs() << "'" << Name.str().c_str() << "'" << "\n";
+
+ if (E->getKind() == EK_Directory) {
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(E);
+ assert(DE && "Should be a directory");
+
+ for (std::unique_ptr<Entry> &SubEntry :
+ llvm::make_range(DE->contents_begin(), DE->contents_end()))
+ dumpEntry(SubEntry.get(), NumSpaces+2);
+ }
+ }
+#endif
+
};
/// \brief A helper class to hold the common YAML parsing state.
@@ -964,7 +1039,71 @@ class RedirectingFileSystemParser {
return true;
}
- std::unique_ptr<Entry> parseEntry(yaml::Node *N) {
+ Entry *lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
+ Entry *ParentEntry = nullptr) {
+ if (!ParentEntry) { // Look for a existent root
+ for (const std::unique_ptr<Entry> &Root : FS->Roots) {
+ if (Name.equals(Root->getName())) {
+ ParentEntry = Root.get();
+ return ParentEntry;
+ }
+ }
+ } else { // Advance to the next component
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(ParentEntry);
+ for (std::unique_ptr<Entry> &Content :
+ llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+ auto *DirContent = dyn_cast<RedirectingDirectoryEntry>(Content.get());
+ if (DirContent && Name.equals(Content->getName()))
+ return DirContent;
+ }
+ }
+
+ // ... or create a new one
+ std::unique_ptr<Entry> E = llvm::make_unique<RedirectingDirectoryEntry>(
+ Name, Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0,
+ 0, file_type::directory_file, sys::fs::all_all));
+
+ if (!ParentEntry) { // Add a new root to the overlay
+ FS->Roots.push_back(std::move(E));
+ ParentEntry = FS->Roots.back().get();
+ return ParentEntry;
+ }
+
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(ParentEntry);
+ DE->addContent(std::move(E));
+ return DE->getLastContent();
+ }
+
+ void uniqueOverlayTree(RedirectingFileSystem *FS, Entry *SrcE,
+ Entry *NewParentE = nullptr) {
+ StringRef Name = SrcE->getName();
+ switch (SrcE->getKind()) {
+ case EK_Directory: {
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE);
+ assert(DE && "Must be a directory");
+ // Empty directories could be present in the YAML as a way to
+ // describe a file for a current directory after some of its subdir
+ // is parsed. This only leads to redundant walks, ignore it.
+ if (!Name.empty())
+ NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
+ for (std::unique_ptr<Entry> &SubEntry :
+ llvm::make_range(DE->contents_begin(), DE->contents_end()))
+ uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
+ break;
+ }
+ case EK_File: {
+ auto *FE = dyn_cast<RedirectingFileEntry>(SrcE);
+ assert(FE && "Must be a file");
+ assert(NewParentE && "Parent entry must exist");
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(NewParentE);
+ DE->addContent(llvm::make_unique<RedirectingFileEntry>(
+ Name, FE->getExternalContentsPath(), FE->getUseName()));
+ break;
+ }
+ }
+ }
+
+ std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS) {
yaml::MappingNode *M = dyn_cast<yaml::MappingNode>(N);
if (!M) {
error(N, "expected mapping node for file or directory entry");
@@ -1004,7 +1143,17 @@ class RedirectingFileSystemParser {
if (Key == "name") {
if (!parseScalarString(I->getValue(), Value, Buffer))
return nullptr;
- Name = Value;
+
+ if (FS->UseCanonicalizedPaths) {
+ SmallString<256> Path(Value);
+ // Guarantee that old YAML files containing paths with ".." and "."
+ // are properly canonicalized before read into the VFS.
+ Path = sys::path::remove_leading_dotslash(Path);
+ sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+ Name = Path.str();
+ } else {
+ Name = Value;
+ }
} else if (Key == "type") {
if (!parseScalarString(I->getValue(), Value, Buffer))
return nullptr;
@@ -1034,7 +1183,7 @@ class RedirectingFileSystemParser {
for (yaml::SequenceNode::iterator I = Contents->begin(),
E = Contents->end();
I != E; ++I) {
- if (std::unique_ptr<Entry> E = parseEntry(&*I))
+ if (std::unique_ptr<Entry> E = parseEntry(&*I, FS))
EntryArrayContents.push_back(std::move(E));
else
return nullptr;
@@ -1048,7 +1197,24 @@ class RedirectingFileSystemParser {
HasContents = true;
if (!parseScalarString(I->getValue(), Value, Buffer))
return nullptr;
- ExternalContentsPath = Value;
+
+ SmallString<256> FullPath;
+ if (FS->IsRelativeOverlay) {
+ FullPath = FS->getExternalContentsPrefixDir();
+ assert(!FullPath.empty() &&
+ "External contents prefix directory must exist");
+ llvm::sys::path::append(FullPath, Value);
+ } else {
+ FullPath = Value;
+ }
+
+ if (FS->UseCanonicalizedPaths) {
+ // Guarantee that old YAML files containing paths with ".." and "."
+ // are properly canonicalized before read into the VFS.
+ FullPath = sys::path::remove_leading_dotslash(FullPath);
+ sys::path::remove_dots(FullPath, /*remove_dot_dot=*/true);
+ }
+ ExternalContentsPath = FullPath.str();
} else if (Key == "use-external-name") {
bool Val;
if (!parseScalarBool(I->getValue(), Val))
@@ -1134,10 +1300,12 @@ public:
KeyStatusPair("version", true),
KeyStatusPair("case-sensitive", false),
KeyStatusPair("use-external-names", false),
+ KeyStatusPair("overlay-relative", false),
KeyStatusPair("roots", true),
};
DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
+ std::vector<std::unique_ptr<Entry>> RootEntries;
// Parse configuration and 'roots'
for (yaml::MappingNode::iterator I = Top->begin(), E = Top->end(); I != E;
@@ -1159,8 +1327,8 @@ public:
for (yaml::SequenceNode::iterator I = Roots->begin(), E = Roots->end();
I != E; ++I) {
- if (std::unique_ptr<Entry> E = parseEntry(&*I))
- FS->Roots.push_back(std::move(E));
+ if (std::unique_ptr<Entry> E = parseEntry(&*I, FS))
+ RootEntries.push_back(std::move(E));
else
return false;
}
@@ -1185,6 +1353,9 @@ public:
} else if (Key == "case-sensitive") {
if (!parseScalarBool(I->getValue(), FS->CaseSensitive))
return false;
+ } else if (Key == "overlay-relative") {
+ if (!parseScalarBool(I->getValue(), FS->IsRelativeOverlay))
+ return false;
} else if (Key == "use-external-names") {
if (!parseScalarBool(I->getValue(), FS->UseExternalNames))
return false;
@@ -1198,6 +1369,13 @@ public:
if (!checkMissingKeys(Top, Keys))
return false;
+
+ // Now that we sucessefully parsed the YAML file, canonicalize the internal
+ // representation to a proper directory tree so that we can search faster
+ // inside the VFS.
+ for (std::unique_ptr<Entry> &E : RootEntries)
+ uniqueOverlayTree(FS, E.get());
+
return true;
}
};
@@ -1205,9 +1383,11 @@ public:
Entry::~Entry() = default;
-RedirectingFileSystem *RedirectingFileSystem::create(
- std::unique_ptr<MemoryBuffer> Buffer, SourceMgr::DiagHandlerTy DiagHandler,
- void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS) {
+RedirectingFileSystem *
+RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
+ SourceMgr::DiagHandlerTy DiagHandler,
+ StringRef YAMLFilePath, void *DiagContext,
+ IntrusiveRefCntPtr<FileSystem> ExternalFS) {
SourceMgr SM;
yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
@@ -1223,7 +1403,24 @@ RedirectingFileSystem *RedirectingFileSystem::create(
RedirectingFileSystemParser P(Stream);
std::unique_ptr<RedirectingFileSystem> FS(
- new RedirectingFileSystem(ExternalFS));
+ new RedirectingFileSystem(std::move(ExternalFS)));
+
+ if (!YAMLFilePath.empty()) {
+ // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
+ // to each 'external-contents' path.
+ //
+ // Example:
+ // -ivfsoverlay dummy.cache/vfs/vfs.yaml
+ // yields:
+ // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs
+ //
+ SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath);
+ std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir);
+ assert(!EC && "Overlay dir final path must be absolute");
+ (void)EC;
+ FS->setExternalContentsPrefixDir(OverlayAbsDir);
+ }
+
if (!P.parse(Root, FS.get()))
return nullptr;
@@ -1238,6 +1435,14 @@ ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
if (std::error_code EC = makeAbsolute(Path))
return EC;
+ // Canonicalize path by removing ".", "..", "./", etc components. This is
+ // a VFS request, do bot bother about symlinks in the path components
+ // but canonicalize in order to perform the correct entry search.
+ if (UseCanonicalizedPaths) {
+ Path = sys::path::remove_leading_dotslash(Path);
+ sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+ }
+
if (Path.empty())
return make_error_code(llvm::errc::invalid_argument);
@@ -1254,20 +1459,32 @@ ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
ErrorOr<Entry *>
RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
sys::path::const_iterator End, Entry *From) {
+#ifndef LLVM_ON_WIN32
+ assert(!isTraversalComponent(*Start) &&
+ !isTraversalComponent(From->getName()) &&
+ "Paths should not contain traversal components");
+#else
+ // FIXME: this is here to support windows, remove it once canonicalized
+ // paths become globally default.
if (Start->equals("."))
++Start;
+#endif
- // FIXME: handle ..
- if (CaseSensitive ? !Start->equals(From->getName())
- : !Start->equals_lower(From->getName()))
- // failure to match
- return make_error_code(llvm::errc::no_such_file_or_directory);
+ StringRef FromName = From->getName();
- ++Start;
+ // Forward the search to the next component in case this is an empty one.
+ if (!FromName.empty()) {
+ if (CaseSensitive ? !Start->equals(FromName)
+ : !Start->equals_lower(FromName))
+ // failure to match
+ return make_error_code(llvm::errc::no_such_file_or_directory);
- if (Start == End) {
- // Match!
- return From;
+ ++Start;
+
+ if (Start == End) {
+ // Match!
+ return From;
+ }
}
auto *DE = dyn_cast<RedirectingDirectoryEntry>(From);
@@ -1322,7 +1539,7 @@ class FileWithFixedStatus : public File {
public:
FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
- : InnerFile(std::move(InnerFile)), S(S) {}
+ : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
ErrorOr<Status> status() override { return S; }
ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
@@ -1362,10 +1579,13 @@ RedirectingFileSystem::openFileForRead(const Twine &Path) {
IntrusiveRefCntPtr<FileSystem>
vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext,
+ SourceMgr::DiagHandlerTy DiagHandler,
+ StringRef YAMLFilePath,
+ void *DiagContext,
IntrusiveRefCntPtr<FileSystem> ExternalFS) {
return RedirectingFileSystem::create(std::move(Buffer), DiagHandler,
- DiagContext, ExternalFS);
+ YAMLFilePath, DiagContext,
+ std::move(ExternalFS));
}
UniqueID vfs::getNextVirtualUniqueID() {
@@ -1376,16 +1596,6 @@ UniqueID vfs::getNextVirtualUniqueID() {
return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
}
-#ifndef NDEBUG
-static bool pathHasTraversal(StringRef Path) {
- using namespace llvm::sys;
- for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
- if (Comp == "." || Comp == "..")
- return true;
- return false;
-}
-#endif
-
void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
assert(sys::path::is_absolute(RealPath) && "real path not absolute");
@@ -1407,7 +1617,9 @@ class JSONWriter {
public:
JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
- void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> IsCaseSensitive);
+ void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
+ Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
+ StringRef OverlayDir);
};
}
@@ -1460,7 +1672,10 @@ void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
}
void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
- Optional<bool> IsCaseSensitive) {
+ Optional<bool> UseExternalNames,
+ Optional<bool> IsCaseSensitive,
+ Optional<bool> IsOverlayRelative,
+ StringRef OverlayDir) {
using namespace llvm::sys;
OS << "{\n"
@@ -1468,12 +1683,30 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
if (IsCaseSensitive.hasValue())
OS << " 'case-sensitive': '"
<< (IsCaseSensitive.getValue() ? "true" : "false") << "',\n";
+ if (UseExternalNames.hasValue())
+ OS << " 'use-external-names': '"
+ << (UseExternalNames.getValue() ? "true" : "false") << "',\n";
+ bool UseOverlayRelative = false;
+ if (IsOverlayRelative.hasValue()) {
+ UseOverlayRelative = IsOverlayRelative.getValue();
+ OS << " 'overlay-relative': '"
+ << (UseOverlayRelative ? "true" : "false") << "',\n";
+ }
OS << " 'roots': [\n";
if (!Entries.empty()) {
const YAMLVFSEntry &Entry = Entries.front();
startDirectory(path::parent_path(Entry.VPath));
- writeEntry(path::filename(Entry.VPath), Entry.RPath);
+
+ StringRef RPath = Entry.RPath;
+ if (UseOverlayRelative) {
+ unsigned OverlayDirLen = OverlayDir.size();
+ assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
+ "Overlay dir must be contained in RPath");
+ RPath = RPath.slice(OverlayDirLen, RPath.size());
+ }
+
+ writeEntry(path::filename(Entry.VPath), RPath);
for (const auto &Entry : Entries.slice(1)) {
StringRef Dir = path::parent_path(Entry.VPath);
@@ -1487,7 +1720,14 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
OS << ",\n";
startDirectory(Dir);
}
- writeEntry(path::filename(Entry.VPath), Entry.RPath);
+ StringRef RPath = Entry.RPath;
+ if (UseOverlayRelative) {
+ unsigned OverlayDirLen = OverlayDir.size();
+ assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
+ "Overlay dir must be contained in RPath");
+ RPath = RPath.slice(OverlayDirLen, RPath.size());
+ }
+ writeEntry(path::filename(Entry.VPath), RPath);
}
while (!DirStack.empty()) {
@@ -1507,7 +1747,8 @@ void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
return LHS.VPath < RHS.VPath;
});
- JSONWriter(OS).write(Mappings, IsCaseSensitive);
+ JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
+ IsOverlayRelative, OverlayDir);
}
VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(