summaryrefslogtreecommitdiff
path: root/clang/lib/Frontend
diff options
context:
space:
mode:
authorMingming Liu <mingmingl@google.com>2025-09-10 15:25:31 -0700
committerGitHub <noreply@github.com>2025-09-10 15:25:31 -0700
commit1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch)
tree57f4b1f313c8cf74eed8819870f39c36ea263c68 /clang/lib/Frontend
parent898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff)
parentb8cefcb601ddaa18482555c4ff363c01a270c2fe (diff)
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'clang/lib/Frontend')
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp218
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp48
-rw-r--r--clang/lib/Frontend/FrontendAction.cpp40
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp101
-rw-r--r--clang/lib/Frontend/InitPreprocessor.cpp6
-rw-r--r--clang/lib/Frontend/LayoutOverrideSource.cpp1
-rw-r--r--clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp61
-rw-r--r--clang/lib/Frontend/Rewrite/RewriteObjC.cpp5
8 files changed, 247 insertions, 233 deletions
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 9f99edadbb70..0a23e0b08ad7 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -57,6 +57,8 @@
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Support/VirtualOutputBackends.h"
+#include "llvm/Support/VirtualOutputError.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include <optional>
@@ -522,6 +524,10 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
collectVFSEntries(*this, ModuleDepCollector);
}
+ // Modules need an output manager.
+ if (!hasOutputManager())
+ createOutputManager();
+
for (auto &Listener : DependencyCollectors)
Listener->attachToPreprocessor(*PP);
@@ -547,10 +553,25 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
PP->setDependencyDirectivesGetter(*GetDependencyDirectives);
}
+void CompilerInstance::normalizeModuleCachePath(
+ FileManager &FileMgr, StringRef Path,
+ SmallVectorImpl<char> &NormalizedPath) {
+ NormalizedPath.assign(Path.begin(), Path.end());
+ FileMgr.makeAbsolutePath(NormalizedPath);
+ llvm::sys::path::remove_dots(NormalizedPath);
+}
+
std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) {
+ assert(FileMgr && "Specific module cache path requires a FileManager");
+
+ if (getHeaderSearchOpts().ModuleCachePath.empty())
+ return "";
+
// Set up the module path, including the hash for the module-creation options.
- SmallString<256> SpecificModuleCache(getHeaderSearchOpts().ModuleCachePath);
- if (!SpecificModuleCache.empty() && !getHeaderSearchOpts().DisableModuleHash)
+ SmallString<256> SpecificModuleCache;
+ normalizeModuleCachePath(*FileMgr, getHeaderSearchOpts().ModuleCachePath,
+ SpecificModuleCache);
+ if (!getHeaderSearchOpts().DisableModuleHash)
llvm::sys::path::append(SpecificModuleCache, ModuleHash);
return std::string(SpecificModuleCache);
}
@@ -778,32 +799,23 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind,
void CompilerInstance::clearOutputFiles(bool EraseFiles) {
// The ASTConsumer can own streams that write to the output files.
assert(!hasASTConsumer() && "ASTConsumer should be reset");
- // Ignore errors that occur when trying to discard the temp file.
- for (OutputFile &OF : OutputFiles) {
- if (EraseFiles) {
- if (OF.File)
- consumeError(OF.File->discard());
- if (!OF.Filename.empty())
- llvm::sys::fs::remove(OF.Filename);
- continue;
- }
-
- if (!OF.File)
- continue;
-
- if (OF.File->TmpName.empty()) {
- consumeError(OF.File->discard());
- continue;
- }
-
- llvm::Error E = OF.File->keep(OF.Filename);
- if (!E)
- continue;
-
- getDiagnostics().Report(diag::err_unable_to_rename_temp)
- << OF.File->TmpName << OF.Filename << std::move(E);
-
- llvm::sys::fs::remove(OF.File->TmpName);
+ if (!EraseFiles) {
+ for (auto &O : OutputFiles)
+ llvm::handleAllErrors(
+ O.keep(),
+ [&](const llvm::vfs::TempFileOutputError &E) {
+ getDiagnostics().Report(diag::err_unable_to_rename_temp)
+ << E.getTempPath() << E.getOutputPath()
+ << E.convertToErrorCode().message();
+ },
+ [&](const llvm::vfs::OutputError &E) {
+ getDiagnostics().Report(diag::err_fe_unable_to_open_output)
+ << E.getOutputPath() << E.convertToErrorCode().message();
+ },
+ [&](const llvm::ErrorInfoBase &EIB) { // Handle any remaining error
+ getDiagnostics().Report(diag::err_fe_unable_to_open_output)
+ << O.getPath() << EIB.message();
+ });
}
OutputFiles.clear();
if (DeleteBuiltModules) {
@@ -837,6 +849,30 @@ std::unique_ptr<raw_pwrite_stream> CompilerInstance::createNullOutputFile() {
return std::make_unique<llvm::raw_null_ostream>();
}
+// Output Manager
+
+void CompilerInstance::setOutputManager(
+ IntrusiveRefCntPtr<llvm::vfs::OutputBackend> NewOutputs) {
+ assert(!OutputMgr && "Already has an output manager");
+ OutputMgr = std::move(NewOutputs);
+}
+
+void CompilerInstance::createOutputManager() {
+ assert(!OutputMgr && "Already has an output manager");
+ OutputMgr = llvm::makeIntrusiveRefCnt<llvm::vfs::OnDiskOutputBackend>();
+}
+
+llvm::vfs::OutputBackend &CompilerInstance::getOutputManager() {
+ assert(OutputMgr);
+ return *OutputMgr;
+}
+
+llvm::vfs::OutputBackend &CompilerInstance::getOrCreateOutputManager() {
+ if (!hasOutputManager())
+ createOutputManager();
+ return getOutputManager();
+}
+
std::unique_ptr<raw_pwrite_stream>
CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary,
bool RemoveFileOnSignal, bool UseTemporary,
@@ -871,98 +907,20 @@ CompilerInstance::createOutputFileImpl(StringRef OutputPath, bool Binary,
OutputPath = *AbsPath;
}
- std::unique_ptr<llvm::raw_fd_ostream> OS;
- std::optional<StringRef> OSFile;
-
- if (UseTemporary) {
- if (OutputPath == "-")
- UseTemporary = false;
- else {
- llvm::sys::fs::file_status Status;
- llvm::sys::fs::status(OutputPath, Status);
- if (llvm::sys::fs::exists(Status)) {
- // Fail early if we can't write to the final destination.
- if (!llvm::sys::fs::can_write(OutputPath))
- return llvm::errorCodeToError(
- make_error_code(llvm::errc::operation_not_permitted));
-
- // Don't use a temporary if the output is a special file. This handles
- // things like '-o /dev/null'
- if (!llvm::sys::fs::is_regular_file(Status))
- UseTemporary = false;
- }
- }
- }
-
- std::optional<llvm::sys::fs::TempFile> Temp;
- if (UseTemporary) {
- // Create a temporary file.
- // Insert -%%%%%%%% before the extension (if any), and because some tools
- // (noticeable, clang's own GlobalModuleIndex.cpp) glob for build
- // artifacts, also append .tmp.
- StringRef OutputExtension = llvm::sys::path::extension(OutputPath);
- SmallString<128> TempPath =
- StringRef(OutputPath).drop_back(OutputExtension.size());
- TempPath += "-%%%%%%%%";
- TempPath += OutputExtension;
- TempPath += ".tmp";
- llvm::sys::fs::OpenFlags BinaryFlags =
- Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text;
- Expected<llvm::sys::fs::TempFile> ExpectedFile =
- llvm::sys::fs::TempFile::create(
- TempPath, llvm::sys::fs::all_read | llvm::sys::fs::all_write,
- BinaryFlags);
-
- llvm::Error E = handleErrors(
- ExpectedFile.takeError(), [&](const llvm::ECError &E) -> llvm::Error {
- std::error_code EC = E.convertToErrorCode();
- if (CreateMissingDirectories &&
- EC == llvm::errc::no_such_file_or_directory) {
- StringRef Parent = llvm::sys::path::parent_path(OutputPath);
- EC = llvm::sys::fs::create_directories(Parent);
- if (!EC) {
- ExpectedFile = llvm::sys::fs::TempFile::create(
- TempPath, llvm::sys::fs::all_read | llvm::sys::fs::all_write,
- BinaryFlags);
- if (!ExpectedFile)
- return llvm::errorCodeToError(
- llvm::errc::no_such_file_or_directory);
- }
- }
- return llvm::errorCodeToError(EC);
- });
-
- if (E) {
- consumeError(std::move(E));
- } else {
- Temp = std::move(ExpectedFile.get());
- OS.reset(new llvm::raw_fd_ostream(Temp->FD, /*shouldClose=*/false));
- OSFile = Temp->TmpName;
- }
- // If we failed to create the temporary, fallback to writing to the file
- // directly. This handles the corner case where we cannot write to the
- // directory, but can write to the file.
- }
-
- if (!OS) {
- OSFile = OutputPath;
- std::error_code EC;
- OS.reset(new llvm::raw_fd_ostream(
- *OSFile, EC,
- (Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_TextWithCRLF)));
- if (EC)
- return llvm::errorCodeToError(EC);
- }
+ using namespace llvm::vfs;
+ Expected<OutputFile> O = getOrCreateOutputManager().createFile(
+ OutputPath,
+ OutputConfig()
+ .setTextWithCRLF(!Binary)
+ .setDiscardOnSignal(RemoveFileOnSignal)
+ .setAtomicWrite(UseTemporary)
+ .setImplyCreateDirectories(UseTemporary && CreateMissingDirectories));
+ if (!O)
+ return O.takeError();
- // Add the output file -- but don't try to remove "-", since this means we are
- // using stdin.
- OutputFiles.emplace_back(((OutputPath != "-") ? OutputPath : "").str(),
- std::move(Temp));
-
- if (!Binary || OS->supportsSeeking())
- return std::move(OS);
-
- return std::make_unique<llvm::buffer_unique_ostream>(std::move(OS));
+ O->discardOnDestroy([](llvm::Error E) { consumeError(std::move(E)); });
+ OutputFiles.push_back(std::move(*O));
+ return OutputFiles.back().createProxy();
}
// Initialization Utilities
@@ -1473,16 +1431,18 @@ static bool compileModuleAndReadASTImpl(CompilerInstance &ImportingInstance,
SourceLocation ModuleNameLoc,
Module *Module,
StringRef ModuleFileName) {
- auto Instance = ImportingInstance.cloneForModuleCompile(ModuleNameLoc, Module,
- ModuleFileName);
-
- if (!ImportingInstance.compileModule(ModuleNameLoc,
- Module->getTopLevelModuleName(),
- ModuleFileName, *Instance)) {
- ImportingInstance.getDiagnostics().Report(ModuleNameLoc,
- diag::err_module_not_built)
- << Module->Name << SourceRange(ImportLoc, ModuleNameLoc);
- return false;
+ {
+ auto Instance = ImportingInstance.cloneForModuleCompile(
+ ModuleNameLoc, Module, ModuleFileName);
+
+ if (!ImportingInstance.compileModule(ModuleNameLoc,
+ Module->getTopLevelModuleName(),
+ ModuleFileName, *Instance)) {
+ ImportingInstance.getDiagnostics().Report(ModuleNameLoc,
+ diag::err_module_not_built)
+ << Module->Name << SourceRange(ImportLoc, ModuleNameLoc);
+ return false;
+ }
}
// The module is built successfully, we can update its timestamp now.
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index da96352e1d82..931766db4b0c 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -623,6 +623,9 @@ static bool FixupInvocation(CompilerInvocation &Invocation,
LangOpts.RawStringLiterals = true;
}
+ LangOpts.NamedLoops =
+ Args.hasFlag(OPT_fnamed_loops, OPT_fno_named_loops, LangOpts.C2y);
+
// Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.
if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)
Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"
@@ -640,6 +643,10 @@ static bool FixupInvocation(CompilerInvocation &Invocation,
Diags.Report(diag::err_drv_argument_not_allowed_with)
<< "-fdx-rootsignature-version" << GetInputKindName(IK);
+ if (Args.hasArg(OPT_fdx_rootsignature_define) && !LangOpts.HLSL)
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << "-fdx-rootsignature-define" << GetInputKindName(IK);
+
if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP)
Diags.Report(diag::warn_ignored_hip_only_option)
<< Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args);
@@ -1315,15 +1322,6 @@ static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions)
Diags->Report(diag::err_analyzer_config_invalid_input)
<< "track-conditions-debug" << "'track-conditions' to also be enabled";
-
- if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir))
- Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir"
- << "a filename";
-
- if (!AnOpts.ModelPath.empty() &&
- !llvm::sys::fs::is_directory(AnOpts.ModelPath))
- Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path"
- << "a filename";
}
/// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.
@@ -3317,9 +3315,6 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
if (Opts.UseLibcxx)
GenerateArg(Consumer, OPT_stdlib_EQ, "libc++");
- if (!Opts.ModuleCachePath.empty())
- GenerateArg(Consumer, OPT_fmodules_cache_path, Opts.ModuleCachePath);
-
for (const auto &File : Opts.PrebuiltModuleFiles)
GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second);
@@ -3422,8 +3417,7 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
}
static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
- DiagnosticsEngine &Diags,
- const std::string &WorkingDir) {
+ DiagnosticsEngine &Diags) {
unsigned NumErrorsBefore = Diags.getNumErrors();
HeaderSearchOptions *HeaderSearchOpts = &Opts;
@@ -3436,17 +3430,6 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
- // Canonicalize -fmodules-cache-path before storing it.
- SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path));
- if (!(P.empty() || llvm::sys::path::is_absolute(P))) {
- if (WorkingDir.empty())
- llvm::sys::fs::make_absolute(P);
- else
- llvm::sys::fs::make_absolute(WorkingDir, P);
- }
- llvm::sys::path::remove_dots(P);
- Opts.ModuleCachePath = std::string(P);
-
// Only the -fmodule-file=<name>=<file> form.
for (const auto *A : Args.filtered(OPT_fmodule_file)) {
StringRef Val = A->getValue();
@@ -3921,9 +3904,6 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_offload_targets_EQ, Targets);
}
- if (!Opts.OMPHostIRFile.empty())
- GenerateArg(Consumer, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile);
-
if (Opts.OpenMPCUDAMode)
GenerateArg(Consumer, OPT_fopenmp_cuda_mode);
@@ -4390,15 +4370,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
}
- // Get OpenMP host file path if any and report if a non existent file is
- // found
- if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {
- Opts.OMPHostIRFile = A->getValue();
- if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
- Diags.Report(diag::err_drv_omp_host_ir_file_not_found)
- << Opts.OMPHostIRFile;
- }
-
// Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options
Opts.OpenMPCUDAMode = Opts.OpenMPIsTargetDevice &&
(T.isNVPTX() || T.isAMDGCN()) &&
@@ -5035,8 +5006,7 @@ bool CompilerInvocation::CreateFromArgsImpl(
InputKind DashX = Res.getFrontendOpts().DashX;
ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
llvm::Triple T(Res.getTargetOpts().Triple);
- ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,
- Res.getFileSystemOpts().WorkingDir);
+ ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags);
if (Res.getFrontendOpts().GenReducedBMI ||
Res.getFrontendOpts().ProgramAction ==
frontend::GenerateReducedModuleInterface ||
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index a7d6a068fe2d..6b1fcac75ac2 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -623,7 +623,7 @@ static std::error_code collectModuleHeaderIncludes(
llvm::sys::path::native(UmbrellaDir->Entry.getName(), DirNative);
llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
- SmallVector<std::pair<std::string, FileEntryRef>, 8> Headers;
+ SmallVector<std::pair<std::string, std::string>, 8> HeaderPaths;
for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;
Dir != End && !EC; Dir.increment(EC)) {
// Check whether this entry has an extension typically associated with
@@ -633,17 +633,6 @@ static std::error_code collectModuleHeaderIncludes(
.Default(false))
continue;
- auto Header = FileMgr.getOptionalFileRef(Dir->path());
- // FIXME: This shouldn't happen unless there is a file system race. Is
- // that worth diagnosing?
- if (!Header)
- continue;
-
- // If this header is marked 'unavailable' in this module, don't include
- // it.
- if (ModMap.isHeaderUnavailableInModule(*Header, Module))
- continue;
-
// Compute the relative path from the directory to this file.
SmallVector<StringRef, 16> Components;
auto PathIt = llvm::sys::path::rbegin(Dir->path());
@@ -655,20 +644,33 @@ static std::error_code collectModuleHeaderIncludes(
++It)
llvm::sys::path::append(RelativeHeader, *It);
- std::string RelName = RelativeHeader.c_str();
- Headers.push_back(std::make_pair(RelName, *Header));
+ HeaderPaths.push_back(
+ std::make_pair(Dir->path().str(), RelativeHeader.c_str()));
}
if (EC)
return EC;
// Sort header paths and make the header inclusion order deterministic
- // across different OSs and filesystems.
- llvm::sort(Headers, llvm::less_first());
- for (auto &H : Headers) {
+ // across different OSs and filesystems. As the header search table
+ // serialization order depends on the file reference UID, we need to create
+ // file references in deterministic order too.
+ llvm::sort(HeaderPaths, llvm::less_first());
+ for (auto &[Path, RelPath] : HeaderPaths) {
+ auto Header = FileMgr.getOptionalFileRef(Path);
+ // FIXME: This shouldn't happen unless there is a file system race. Is
+ // that worth diagnosing?
+ if (!Header)
+ continue;
+
+ // If this header is marked 'unavailable' in this module, don't include
+ // it.
+ if (ModMap.isHeaderUnavailableInModule(*Header, Module))
+ continue;
+
// Include this header as part of the umbrella directory.
- Module->addTopHeader(H.second);
- addHeaderInclude(H.first, Includes, LangOpts, Module->IsExternC);
+ Module->addTopHeader(*Header);
+ addHeaderInclude(RelPath, Includes, LangOpts, Module->IsExternC);
}
}
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 685a9bbf2cde..7424958d4661 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -22,6 +22,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Parse/ParseHLSLRootSignature.h"
#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
@@ -795,9 +796,10 @@ namespace {
/// Indicates that the AST file contains particular input file.
///
/// \returns true to continue receiving the next input file, false to stop.
- bool visitInputFile(StringRef FilenameAsRequested, StringRef Filename,
- bool isSystem, bool isOverridden,
- bool isExplicitModule) override {
+ bool visitInputFileAsRequested(StringRef FilenameAsRequested,
+ StringRef Filename, bool isSystem,
+ bool isOverridden,
+ bool isExplicitModule) override {
Out.indent(2) << "Input file: " << FilenameAsRequested;
@@ -1241,3 +1243,96 @@ void GetDependenciesByModuleNameAction::ExecuteAction() {
PPCallbacks *CB = PP.getPPCallbacks();
CB->moduleImport(SourceLocation(), Path, ModResult);
}
+
+//===----------------------------------------------------------------------===//
+// HLSL Specific Actions
+//===----------------------------------------------------------------------===//
+
+class InjectRootSignatureCallback : public PPCallbacks {
+private:
+ Sema &Actions;
+ StringRef RootSigName;
+ llvm::dxbc::RootSignatureVersion Version;
+
+ std::optional<StringLiteral *> processStringLiteral(ArrayRef<Token> Tokens) {
+ for (Token Tok : Tokens)
+ if (!tok::isStringLiteral(Tok.getKind()))
+ return std::nullopt;
+
+ ExprResult StringResult = Actions.ActOnUnevaluatedStringLiteral(Tokens);
+ if (StringResult.isInvalid())
+ return std::nullopt;
+
+ if (auto Signature = dyn_cast<StringLiteral>(StringResult.get()))
+ return Signature;
+
+ return std::nullopt;
+ }
+
+public:
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override {
+ if (RootSigName != MacroNameTok.getIdentifierInfo()->getName())
+ return;
+
+ const MacroInfo *MI = MD->getMacroInfo();
+ auto Signature = processStringLiteral(MI->tokens());
+ if (!Signature.has_value()) {
+ Actions.getDiagnostics().Report(MI->getDefinitionLoc(),
+ diag::err_expected_string_literal)
+ << /*in attributes...*/ 4 << "RootSignature";
+ return;
+ }
+
+ IdentifierInfo *DeclIdent =
+ hlsl::ParseHLSLRootSignature(Actions, Version, *Signature);
+ Actions.HLSL().SetRootSignatureOverride(DeclIdent);
+ }
+
+ InjectRootSignatureCallback(Sema &Actions, StringRef RootSigName,
+ llvm::dxbc::RootSignatureVersion Version)
+ : PPCallbacks(), Actions(Actions), RootSigName(RootSigName),
+ Version(Version) {}
+};
+
+void HLSLFrontendAction::ExecuteAction() {
+ // Pre-requisites to invoke
+ CompilerInstance &CI = getCompilerInstance();
+ if (!CI.hasASTContext() || !CI.hasPreprocessor())
+ return WrapperFrontendAction::ExecuteAction();
+
+ // InjectRootSignatureCallback requires access to invoke Sema to lookup/
+ // register a root signature declaration. The wrapped action is required to
+ // account for this by only creating a Sema if one doesn't already exist
+ // (like we have done, and, ASTFrontendAction::ExecuteAction)
+ if (!CI.hasSema())
+ CI.createSema(getTranslationUnitKind(),
+ /*CodeCompleteConsumer=*/nullptr);
+ Sema &S = CI.getSema();
+
+ auto &TargetInfo = CI.getASTContext().getTargetInfo();
+ bool IsRootSignatureTarget =
+ TargetInfo.getTriple().getEnvironment() == llvm::Triple::RootSignature;
+ StringRef HLSLEntry = TargetInfo.getTargetOpts().HLSLEntry;
+
+ // Register HLSL specific callbacks
+ auto LangOpts = CI.getLangOpts();
+ StringRef RootSigName =
+ IsRootSignatureTarget ? HLSLEntry : LangOpts.HLSLRootSigOverride;
+
+ auto MacroCallback = std::make_unique<InjectRootSignatureCallback>(
+ S, RootSigName, LangOpts.HLSLRootSigVer);
+
+ Preprocessor &PP = CI.getPreprocessor();
+ PP.addPPCallbacks(std::move(MacroCallback));
+
+ // If we are targeting a root signature, invoke custom handling
+ if (IsRootSignatureTarget)
+ return hlsl::HandleRootSignatureTarget(S, HLSLEntry);
+ else // otherwise, invoke as normal
+ return WrapperFrontendAction::ExecuteAction();
+}
+
+HLSLFrontendAction::HLSLFrontendAction(
+ std::unique_ptr<FrontendAction> WrappedAction)
+ : WrapperFrontendAction(std::move(WrappedAction)) {}
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 4865c0b88904..e65c8b4f6fac 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1519,9 +1519,11 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (TI.getTriple().isOSBinFormatELF())
Builder.defineMacro("__ELF__");
- if (LangOpts.Sanitize.has(SanitizerKind::Address))
+ if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
Builder.defineMacro("__SANITIZE_ADDRESS__");
- if (LangOpts.Sanitize.has(SanitizerKind::HWAddress))
+ if (LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress |
+ SanitizerKind::KernelHWAddress))
Builder.defineMacro("__SANITIZE_HWADDRESS__");
if (LangOpts.Sanitize.has(SanitizerKind::Thread))
Builder.defineMacro("__SANITIZE_THREAD__");
diff --git a/clang/lib/Frontend/LayoutOverrideSource.cpp b/clang/lib/Frontend/LayoutOverrideSource.cpp
index a1866ec09c9d..0a60e00e5cb1 100644
--- a/clang/lib/Frontend/LayoutOverrideSource.cpp
+++ b/clang/lib/Frontend/LayoutOverrideSource.cpp
@@ -8,6 +8,7 @@
#include "clang/Frontend/LayoutOverrideSource.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/Support/raw_ostream.h"
#include <fstream>
diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 2b55820b3880..42f2d6591b21 100644
--- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -852,7 +852,7 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {
- RecordDecl *RD = IvarT->castAs<RecordType>()->getOriginalDecl();
+ RecordDecl *RD = IvarT->castAsCanonical<RecordType>()->getOriginalDecl();
RD = RD->getDefinition();
if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
// decltype(((Foo_IMPL*)0)->bar) *
@@ -3638,8 +3638,7 @@ bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
return RewriteObjCFieldDeclType(ElemTy, Result);
}
else if (Type->isRecordType()) {
- RecordDecl *RD =
- Type->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
+ auto *RD = Type->castAsRecordDecl();
if (RD->isCompleteDefinition()) {
if (RD->isStruct())
Result += "\n\tstruct ";
@@ -3660,28 +3659,26 @@ bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
Result += "\t} ";
return true;
}
- }
- else if (Type->isEnumeralType()) {
- EnumDecl *ED =
- Type->castAs<EnumType>()->getOriginalDecl()->getDefinitionOrSelf();
- if (ED->isCompleteDefinition()) {
- Result += "\n\tenum ";
- Result += ED->getName();
- if (GlobalDefinedTags.count(ED)) {
- // Enum is globall defined, use it.
- Result += " ";
- return true;
- }
-
- Result += " {\n";
- for (const auto *EC : ED->enumerators()) {
- Result += "\t"; Result += EC->getName(); Result += " = ";
- Result += toString(EC->getInitVal(), 10);
- Result += ",\n";
- }
- Result += "\t} ";
+ } else if (auto *ED = Type->getAsEnumDecl();
+ ED && ED->isCompleteDefinition()) {
+ Result += "\n\tenum ";
+ Result += ED->getName();
+ if (GlobalDefinedTags.count(ED)) {
+ // Enum is globall defined, use it.
+ Result += " ";
return true;
}
+
+ Result += " {\n";
+ for (const auto *EC : ED->enumerators()) {
+ Result += "\t";
+ Result += EC->getName();
+ Result += " = ";
+ Result += toString(EC->getInitVal(), 10);
+ Result += ",\n";
+ }
+ Result += "\t} ";
+ return true;
}
Result += "\t";
@@ -3733,15 +3730,7 @@ void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDec
auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());
- TagDecl *TD = nullptr;
- if (Type->isRecordType()) {
- TD = Type->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
- }
- else if (Type->isEnumeralType()) {
- TD = Type->castAs<EnumType>()->getOriginalDecl()->getDefinitionOrSelf();
- }
-
- if (TD) {
+ if (auto *TD = Type->getAsTagDecl()) {
if (GlobalDefinedTags.count(TD))
return;
@@ -5723,10 +5712,7 @@ void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {
}
}
} else if (VD->getType()->isRecordType()) {
- RecordDecl *RD = VD->getType()
- ->castAs<RecordType>()
- ->getOriginalDecl()
- ->getDefinitionOrSelf();
+ auto *RD = VD->getType()->castAsRecordDecl();
if (RD->isCompleteDefinition())
RewriteRecordBody(RD);
}
@@ -7467,7 +7453,8 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {
- RecordDecl *RD = IvarT->castAs<RecordType>()->getOriginalDecl();
+ RecordDecl *RD =
+ IvarT->castAsCanonical<RecordType>()->getOriginalDecl();
RD = RD->getDefinition();
if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
// decltype(((Foo_IMPL*)0)->bar) *
diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 0242fc1f6e82..b9c025de8773 100644
--- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -4835,10 +4835,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
}
}
} else if (VD->getType()->isRecordType()) {
- RecordDecl *RD = VD->getType()
- ->castAs<RecordType>()
- ->getOriginalDecl()
- ->getDefinitionOrSelf();
+ auto *RD = VD->getType()->castAsRecordDecl();
if (RD->isCompleteDefinition())
RewriteRecordBody(RD);
}