132 changes: 121 additions & 11 deletions clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
#include "llvm/TargetParser/Host.h"
Expand Down Expand Up @@ -67,7 +68,7 @@ static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
if (LangOpts.Modules) {
if (HSOpts.VFSOverlayFiles != ExistingHSOpts.VFSOverlayFiles) {
if (Diags) {
Diags->Report(diag::err_pch_vfsoverlay_mismatch);
Diags->Report(diag::warn_pch_vfsoverlay_mismatch);
auto VFSNote = [&](int Type, ArrayRef<std::string> VFSOverlays) {
if (VFSOverlays.empty()) {
Diags->Report(diag::note_pch_vfsoverlay_empty) << Type;
Expand All @@ -79,7 +80,6 @@ static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
VFSNote(0, HSOpts.VFSOverlayFiles);
VFSNote(1, ExistingHSOpts.VFSOverlayFiles);
}
return true;
}
}
return false;
Expand All @@ -93,10 +93,12 @@ class PrebuiltModuleListener : public ASTReaderListener {
public:
PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
llvm::SmallVector<std::string> &NewModuleFiles,
PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap,
const HeaderSearchOptions &HSOpts,
const LangOptions &LangOpts, DiagnosticsEngine &Diags)
: PrebuiltModuleFiles(PrebuiltModuleFiles),
NewModuleFiles(NewModuleFiles), ExistingHSOpts(HSOpts),
NewModuleFiles(NewModuleFiles),
PrebuiltModuleVFSMap(PrebuiltModuleVFSMap), ExistingHSOpts(HSOpts),
ExistingLangOpts(LangOpts), Diags(Diags) {}

bool needsImportVisitation() const override { return true; }
Expand All @@ -106,31 +108,45 @@ class PrebuiltModuleListener : public ASTReaderListener {
NewModuleFiles.push_back(Filename.str());
}

void visitModuleFile(StringRef Filename,
serialization::ModuleKind Kind) override {
CurrentFile = Filename;
}

bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
bool Complain) override {
std::vector<std::string> VFSOverlayFiles = HSOpts.VFSOverlayFiles;
PrebuiltModuleVFSMap.insert(
{CurrentFile, llvm::StringSet<>(VFSOverlayFiles)});
return checkHeaderSearchPaths(
HSOpts, ExistingHSOpts, Complain ? &Diags : nullptr, ExistingLangOpts);
}

private:
PrebuiltModuleFilesT &PrebuiltModuleFiles;
llvm::SmallVector<std::string> &NewModuleFiles;
PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap;
const HeaderSearchOptions &ExistingHSOpts;
const LangOptions &ExistingLangOpts;
DiagnosticsEngine &Diags;
std::string CurrentFile;
};

/// Visit the given prebuilt module and collect all of the modules it
/// transitively imports and contributing input files.
static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
CompilerInstance &CI,
PrebuiltModuleFilesT &ModuleFiles,
PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap,
DiagnosticsEngine &Diags) {
// List of module files to be processed.
llvm::SmallVector<std::string> Worklist;
PrebuiltModuleListener Listener(
ModuleFiles, Worklist, CI.getHeaderSearchOpts(), CI.getLangOpts(), Diags);
PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModuleVFSMap,
CI.getHeaderSearchOpts(), CI.getLangOpts(),
Diags);

Listener.visitModuleFile(PrebuiltModuleFilename,
serialization::MK_ExplicitModule);
if (ASTReader::readASTFileControlBlock(
PrebuiltModuleFilename, CI.getFileManager(), CI.getModuleCache(),
CI.getPCHContainerReader(),
Expand All @@ -139,6 +155,7 @@ static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
return true;

while (!Worklist.empty()) {
Listener.visitModuleFile(Worklist.back(), serialization::MK_ExplicitModule);
if (ASTReader::readASTFileControlBlock(
Worklist.pop_back_val(), CI.getFileManager(), CI.getModuleCache(),
CI.getPCHContainerReader(),
Expand Down Expand Up @@ -175,8 +192,91 @@ static void sanitizeDiagOpts(DiagnosticOptions &DiagOpts) {
DiagOpts.ShowCarets = false;
// Don't write out diagnostic file.
DiagOpts.DiagnosticSerializationFile.clear();
// Don't emit warnings as errors (and all other warnings too).
DiagOpts.IgnoreWarnings = true;
// Don't emit warnings except for scanning specific warnings.
// TODO: It would be useful to add a more principled way to ignore all
// warnings that come from source code. The issue is that we need to
// ignore warnings that could be surpressed by
// `#pragma clang diagnostic`, while still allowing some scanning
// warnings for things we're not ready to turn into errors yet.
// See `test/ClangScanDeps/diagnostic-pragmas.c` for an example.
llvm::erase_if(DiagOpts.Warnings, [](StringRef Warning) {
return llvm::StringSwitch<bool>(Warning)
.Cases("pch-vfs-diff", "error=pch-vfs-diff", false)
.StartsWith("no-error=", false)
.Default(true);
});
}

// Clang implements -D and -U by splatting text into a predefines buffer. This
// allows constructs such as `-DFඞ=3 "-D F\u{0D9E} 4 3 2”` to be accepted and
// define the same macro, or adding C++ style comments before the macro name.
//
// This function checks that the first non-space characters in the macro
// obviously form an identifier that can be uniqued on without lexing. Failing
// to do this could lead to changing the final definition of a macro.
//
// We could set up a preprocessor and actually lex the name, but that's very
// heavyweight for a situation that will almost never happen in practice.
static std::optional<StringRef> getSimpleMacroName(StringRef Macro) {
StringRef Name = Macro.split("=").first.ltrim(" \t");
std::size_t I = 0;

auto FinishName = [&]() -> std::optional<StringRef> {
StringRef SimpleName = Name.slice(0, I);
if (SimpleName.empty())
return std::nullopt;
return SimpleName;
};

for (; I != Name.size(); ++I) {
switch (Name[I]) {
case '(': // Start of macro parameter list
case ' ': // End of macro name
case '\t':
return FinishName();
case '_':
continue;
default:
if (llvm::isAlnum(Name[I]))
continue;
return std::nullopt;
}
}
return FinishName();
}

static void canonicalizeDefines(PreprocessorOptions &PPOpts) {
using MacroOpt = std::pair<StringRef, std::size_t>;
std::vector<MacroOpt> SimpleNames;
SimpleNames.reserve(PPOpts.Macros.size());
std::size_t Index = 0;
for (const auto &M : PPOpts.Macros) {
auto SName = getSimpleMacroName(M.first);
// Skip optimizing if we can't guarantee we can preserve relative order.
if (!SName)
return;
SimpleNames.emplace_back(*SName, Index);
++Index;
}

llvm::stable_sort(SimpleNames, [](const MacroOpt &A, const MacroOpt &B) {
return A.first < B.first;
});
// Keep the last instance of each macro name by going in reverse
auto NewEnd = std::unique(
SimpleNames.rbegin(), SimpleNames.rend(),
[](const MacroOpt &A, const MacroOpt &B) { return A.first == B.first; });
SimpleNames.erase(SimpleNames.begin(), NewEnd.base());

// Apply permutation.
decltype(PPOpts.Macros) NewMacros;
NewMacros.reserve(SimpleNames.size());
for (std::size_t I = 0, E = SimpleNames.size(); I != E; ++I) {
std::size_t OriginalIndex = SimpleNames[I].second;
// We still emit undefines here as they may be undefining a predefined macro
NewMacros.push_back(std::move(PPOpts.Macros[OriginalIndex]));
}
std::swap(PPOpts.Macros, NewMacros);
}

/// A clang tool that runs the preprocessor in a mode that's optimized for
Expand All @@ -203,6 +303,8 @@ class DependencyScanningAction : public tooling::ToolAction {
CompilerInvocation OriginalInvocation(*Invocation);
// Restore the value of DisableFree, which may be modified by Tooling.
OriginalInvocation.getFrontendOpts().DisableFree = DisableFree;
if (any(OptimizeArgs & ScanningOptimizations::Macros))
canonicalizeDefines(OriginalInvocation.getPreprocessorOpts());

if (Scanned) {
// Scanning runs once for the first -cc1 invocation in a chain of driver
Expand All @@ -226,14 +328,19 @@ class DependencyScanningAction : public tooling::ToolAction {
if (!ScanInstance.hasDiagnostics())
return false;

// Some DiagnosticConsumers require that finish() is called.
auto DiagConsumerFinisher =
llvm::make_scope_exit([DiagConsumer]() { DiagConsumer->finish(); });

ScanInstance.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath =
true;

ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false;
ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false;
ScanInstance.getFrontendOpts().ModulesShareFileManager = false;
ScanInstance.getHeaderSearchOpts().ModuleFormat = "raw";
ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage = true;
ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage =
any(OptimizeArgs & ScanningOptimizations::VFS);

ScanInstance.setFileManager(FileMgr);
// Support for virtual file system overlays.
Expand All @@ -246,12 +353,13 @@ class DependencyScanningAction : public tooling::ToolAction {
// Store the list of prebuilt module files into header search options. This
// will prevent the implicit build to create duplicate modules and will
// force reuse of the existing prebuilt module files instead.
PrebuiltModuleVFSMapT PrebuiltModuleVFSMap;
if (!ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
if (visitPrebuiltModule(
ScanInstance.getPreprocessorOpts().ImplicitPCHInclude,
ScanInstance,
ScanInstance.getHeaderSearchOpts().PrebuiltModuleFiles,
ScanInstance.getDiagnostics()))
PrebuiltModuleVFSMap, ScanInstance.getDiagnostics()))
return false;

// Use the dependency scanning optimized file system if requested to do so.
Expand Down Expand Up @@ -295,8 +403,8 @@ class DependencyScanningAction : public tooling::ToolAction {
case ScanningOutputFormat::Full:
MDC = std::make_shared<ModuleDepCollector>(
std::move(Opts), ScanInstance, Consumer, Controller,
OriginalInvocation, OptimizeArgs, EagerLoadModules,
Format == ScanningOutputFormat::P1689);
OriginalInvocation, std::move(PrebuiltModuleVFSMap), OptimizeArgs,
EagerLoadModules, Format == ScanningOutputFormat::P1689);
ScanInstance.addDependencyCollector(MDC);
break;
}
Expand Down Expand Up @@ -325,6 +433,8 @@ class DependencyScanningAction : public tooling::ToolAction {
if (ScanInstance.getDiagnostics().hasErrorOccurred())
return false;

// Each action is responsible for calling finish.
DiagConsumerFinisher.release();
const bool Result = ScanInstance.ExecuteAction(*Action);

if (Result)
Expand Down
34 changes: 26 additions & 8 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ const std::vector<std::string> &ModuleDeps::getBuildArguments() {
return std::get<std::vector<std::string>>(BuildInfo);
}

static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts,
ASTReader &Reader,
const serialization::ModuleFile &MF,
ScanningOptimizations OptimizeArgs) {
static void
optimizeHeaderSearchOpts(HeaderSearchOptions &Opts, ASTReader &Reader,
const serialization::ModuleFile &MF,
const PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap,
ScanningOptimizations OptimizeArgs) {
if (any(OptimizeArgs & ScanningOptimizations::HeaderSearch)) {
// Only preserve search paths that were used during the dependency scan.
std::vector<HeaderSearchOptions::Entry> Entries;
Expand Down Expand Up @@ -65,11 +66,25 @@ static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts,
llvm::DenseSet<const serialization::ModuleFile *> Visited;
std::function<void(const serialization::ModuleFile *)> VisitMF =
[&](const serialization::ModuleFile *MF) {
VFSUsage |= MF->VFSUsage;
Visited.insert(MF);
for (const serialization::ModuleFile *Import : MF->Imports)
if (!Visited.contains(Import))
VisitMF(Import);
if (MF->Kind == serialization::MK_ImplicitModule) {
VFSUsage |= MF->VFSUsage;
// We only need to recurse into implicit modules. Other module types
// will have the correct set of VFSs for anything they depend on.
for (const serialization::ModuleFile *Import : MF->Imports)
if (!Visited.contains(Import))
VisitMF(Import);
} else {
// This is not an implicitly built module, so it may have different
// VFS options. Fall back to a string comparison instead.
auto VFSMap = PrebuiltModuleVFSMap.find(MF->FileName);
if (VFSMap == PrebuiltModuleVFSMap.end())
return;
for (std::size_t I = 0, E = VFSOverlayFiles.size(); I != E; ++I) {
if (VFSMap->second.contains(VFSOverlayFiles[I]))
VFSUsage[I] = true;
}
}
};
VisitMF(&MF);

Expand Down Expand Up @@ -596,6 +611,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
ScanningOptimizations::VFS)))
optimizeHeaderSearchOpts(BuildInvocation.getMutHeaderSearchOpts(),
*MDC.ScanInstance.getASTReader(), *MF,
MDC.PrebuiltModuleVFSMap,
MDC.OptimizeArgs);
if (any(MDC.OptimizeArgs & ScanningOptimizations::SystemWarnings))
optimizeDiagnosticOpts(
Expand Down Expand Up @@ -697,9 +713,11 @@ ModuleDepCollector::ModuleDepCollector(
std::unique_ptr<DependencyOutputOptions> Opts,
CompilerInstance &ScanInstance, DependencyConsumer &C,
DependencyActionController &Controller, CompilerInvocation OriginalCI,
PrebuiltModuleVFSMapT PrebuiltModuleVFSMap,
ScanningOptimizations OptimizeArgs, bool EagerLoadModules,
bool IsStdModuleP1689Format)
: ScanInstance(ScanInstance), Consumer(C), Controller(Controller),
PrebuiltModuleVFSMap(std::move(PrebuiltModuleVFSMap)),
Opts(std::move(Opts)),
CommonInvocation(
makeCommonInvocationForModuleBuild(std::move(OriginalCI))),
Expand Down
51 changes: 49 additions & 2 deletions clang/test/AST/Interp/atomic.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected %s
// RUN: %clang_cc1 -verify=both,ref %s
// RUN: %clang_cc1 -fgnuc-version=4.2.1 -triple=i686-linux-gnu -ffreestanding -fexperimental-new-constant-interpreter -verify=both,expected %s
// RUN: %clang_cc1 -fgnuc-version=4.2.1 -triple=i686-linux-gnu -ffreestanding -verify=both,ref %s

/// FIXME: Copied from test/Sema/atomic-expr.c.
/// this expression seems to be rejected for weird reasons,
Expand All @@ -11,3 +11,50 @@ _Atomic int ai = 0;
// The warning is correct but the error is not.
_Atomic(int *) aip3 = &ai; // both-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}} \
// both-error {{initializer element is not a compile-time constant}}

#include <stdatomic.h>



_Static_assert(__GCC_ATOMIC_BOOL_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_BOOL_LOCK_FREE == __CLANG_ATOMIC_BOOL_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_CHAR_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_CHAR_LOCK_FREE == __CLANG_ATOMIC_CHAR_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_CHAR16_T_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_CHAR16_T_LOCK_FREE == __CLANG_ATOMIC_CHAR16_T_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_CHAR32_T_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_CHAR32_T_LOCK_FREE == __CLANG_ATOMIC_CHAR32_T_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_WCHAR_T_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_WCHAR_T_LOCK_FREE == __CLANG_ATOMIC_WCHAR_T_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_SHORT_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_SHORT_LOCK_FREE == __CLANG_ATOMIC_SHORT_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_INT_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_INT_LOCK_FREE == __CLANG_ATOMIC_INT_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_LONG_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_LONG_LOCK_FREE == __CLANG_ATOMIC_LONG_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_LLONG_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_LLONG_LOCK_FREE == __CLANG_ATOMIC_LLONG_LOCK_FREE, "");
_Static_assert(__GCC_ATOMIC_POINTER_LOCK_FREE == 2, "");
_Static_assert(__GCC_ATOMIC_POINTER_LOCK_FREE == __CLANG_ATOMIC_POINTER_LOCK_FREE, "");

_Static_assert(__c11_atomic_is_lock_free(1), "");
_Static_assert(__c11_atomic_is_lock_free(2), "");
_Static_assert(__c11_atomic_is_lock_free(3), ""); // both-error {{not an integral constant expression}}
_Static_assert(__c11_atomic_is_lock_free(4), "");
_Static_assert(__c11_atomic_is_lock_free(8), "");
_Static_assert(__c11_atomic_is_lock_free(16), ""); // both-error {{not an integral constant expression}}
_Static_assert(__c11_atomic_is_lock_free(17), ""); // both-error {{not an integral constant expression}}

_Static_assert(__atomic_is_lock_free(1, 0), "");
_Static_assert(__atomic_is_lock_free(2, 0), "");
_Static_assert(__atomic_is_lock_free(3, 0), ""); // both-error {{not an integral constant expression}}
_Static_assert(__atomic_is_lock_free(4, 0), "");
_Static_assert(__atomic_is_lock_free(8, 0), "");
_Static_assert(__atomic_is_lock_free(16, 0), ""); // both-error {{not an integral constant expression}}
_Static_assert(__atomic_is_lock_free(17, 0), ""); // both-error {{not an integral constant expression}}

_Static_assert(atomic_is_lock_free((atomic_char*)0), "");
_Static_assert(atomic_is_lock_free((atomic_short*)0), "");
_Static_assert(atomic_is_lock_free((atomic_int*)0), "");
_Static_assert(atomic_is_lock_free((atomic_long*)0), "");
_Static_assert(atomic_is_lock_free(0 + (atomic_char*)0), "");
3 changes: 3 additions & 0 deletions clang/test/AST/Interp/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ _Static_assert(!!1.0, ""); // pedantic-ref-warning {{not an integer constant exp
// pedantic-expected-warning {{not an integer constant expression}}
_Static_assert(!!1, "");

_Static_assert(!(_Bool){(void*)0}, ""); // pedantic-ref-warning {{not an integer constant expression}} \
// pedantic-expected-warning {{not an integer constant expression}}

int a = (1 == 1 ? 5 : 3);
_Static_assert(a == 5, ""); // all-error {{not an integral constant expression}}

Expand Down
31 changes: 31 additions & 0 deletions clang/test/AST/Interp/complex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ void func(void) {
result = arr * ii;
}

constexpr _Complex float getComplexFloat() {
return {1,2};
}
static_assert(__real(getComplexFloat()) == 1, "");
static_assert(__imag(getComplexFloat()) == 2, "");

namespace CastToBool {
constexpr _Complex int F = {0, 1};
static_assert(F, "");
Expand Down Expand Up @@ -164,6 +170,20 @@ namespace Add {
constexpr _Complex unsigned int I3 = I1 + I2;
static_assert(__real(I3) == 45, "");
static_assert(__imag(I3) == 12, "");

static_assert(__real(A + 2.0) == 15, "");
static_assert(__imag(A + 2.0) == 2, "");
static_assert(__real(2.0 + A) == 15, "");
static_assert(__imag(2.0 + A) == 2, "");

static_assert(__real(D + 1) == 16, "");
static_assert(__real(D + 1.0) == 16, "");
constexpr _Complex double D2 = D + 3.0;
static_assert(__real(D2) == 18.0, "");
static_assert(__imag(D2) == 3.0, "");
constexpr _Complex double D3 = 3.0 + D;
static_assert(__real(D3) == 18.0, "");
static_assert(__imag(D3) == 3.0, "");
}

namespace Sub {
Expand All @@ -172,6 +192,8 @@ namespace Sub {
constexpr _Complex float C = A - B;
static_assert(__real(C) == 11.0, "");
static_assert(__imag(C) == 1.0, "");
static_assert(__real(A - 2.0) == 11, "");
static_assert(__real(2.0 - A) == -11, "");

constexpr _Complex float D = B - A;
static_assert(__real(D) == -11.0, "");
Expand All @@ -189,6 +211,15 @@ namespace Sub {
constexpr _Complex float D_ = A_ - B_;
static_assert(__real(D_) == 11.0, "");
static_assert(__imag(D_) == 1.0, "");

static_assert(__real(D - 1) == -12, "");
static_assert(__real(D - 1.0) == -12, "");
constexpr _Complex double D2 = D - 3.0;
static_assert(__real(D2) == -14.0, "");
static_assert(__imag(D2) == -1.0, "");
constexpr _Complex double D3 = 3.0 - D;
static_assert(__real(D3) == 14.0, "");
static_assert(__imag(D3) == 1.0, "");
}

}
Expand Down
5 changes: 4 additions & 1 deletion clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,12 @@ namespace FunctionPointers {
}

constexpr int applyBinOp(int a, int b, int (*op)(int, int)) {
return op(a, b);
return op(a, b); // both-note {{evaluates to a null function pointer}}
}
static_assert(applyBinOp(1, 2, add) == 3, "");
static_assert(applyBinOp(1, 2, nullptr) == 3, ""); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}


constexpr int ignoreReturnValue() {
int (*foo)(int, int) = add;
Expand Down
77 changes: 77 additions & 0 deletions clang/test/AST/Interp/nullable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -verify=ref,both %s


constexpr int dummy = 1;
constexpr const int *null = nullptr;

namespace simple {
__attribute__((nonnull))
constexpr int simple1(const int*) {
return 1;
}
static_assert(simple1(&dummy) == 1, "");
static_assert(simple1(nullptr) == 1, ""); // both-error {{not an integral constant expression}} \
// both-note {{null passed to a callee}}
static_assert(simple1(null) == 1, ""); // both-error {{not an integral constant expression}} \
// both-note {{null passed to a callee}}

__attribute__((nonnull)) // both-warning {{applied to function with no pointer arguments}}
constexpr int simple2(const int &a) {
return 12;
}
static_assert(simple2(1) == 12, "");
}

namespace methods {
struct S {
__attribute__((nonnull(2))) // both-warning {{only applies to pointer arguments}}
__attribute__((nonnull(3)))
constexpr int foo(int a, const void *p) const {
return 12;
}

__attribute__((nonnull(3)))
constexpr int foo2(...) const {
return 12;
}

__attribute__((nonnull))
constexpr int foo3(...) const {
return 12;
}
};

constexpr S s{};
static_assert(s.foo(8, &dummy) == 12, "");

static_assert(s.foo2(nullptr) == 12, "");
static_assert(s.foo2(1, nullptr) == 12, ""); // both-error {{not an integral constant expression}} \
// both-note {{null passed to a callee}}

constexpr S *s2 = nullptr;
static_assert(s2->foo3() == 12, ""); // both-error {{not an integral constant expression}} \
// both-note {{member call on dereferenced null pointer}}
}

namespace fnptrs {
__attribute__((nonnull))
constexpr int add(int a, const void *p) {
return a + 1;
}
__attribute__((nonnull(3)))
constexpr int applyBinOp(int a, int b, int (*op)(int, const void *)) {
return op(a, nullptr); // both-note {{null passed to a callee}}
}
static_assert(applyBinOp(10, 20, add) == 11, ""); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}

static_assert(applyBinOp(10, 20, nullptr) == 11, ""); // both-error {{not an integral constant expression}} \
// both-note {{null passed to a callee}}
}

namespace lambdas {
auto lstatic = [](const void *P) __attribute__((nonnull)) { return 3; };
static_assert(lstatic(nullptr) == 3, ""); // both-error {{not an integral constant expression}} \
// both-note {{null passed to a callee}}
}
74 changes: 74 additions & 0 deletions clang/test/CXX/except/except.spec/p13.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s

struct A {
static constexpr bool x = true;
};

namespace N0 {

template<typename T, typename U>
void f(T, U) noexcept(T::y); // #1

template<typename T, typename U> // #2
void f(T, U*) noexcept(T::x);

// Deduction should succeed for both candidates, and #2 should be selected as the primary template.
// Only the exception specification of #2 should be instantiated.
template<>
void f(A, int*) noexcept;

}

namespace N1 {

template<typename T, typename U>
void f(T, U) noexcept(T::x); // #1

template<typename T, typename U>
void f(T, U*) noexcept(T::y); // #2
// expected-error@-1 {{no member named 'y' in 'A'}}

// Deduction should succeed for both candidates, and #2 should be selected as the primary template.
// Only the exception specification of #2 should be instantiated.
template<>
void f(A, int*) noexcept; // expected-error {{exception specification in declaration does not match previous declaration}}
// expected-note@-1 {{in instantiation of exception specification for 'f<A, int>' requested here}}
// expected-note@-2 {{previous declaration is here}}
}

namespace N2 {

template<typename T, typename U>
void f(T, U) noexcept(T::x);

template<typename T, typename U>
void f(T, U*) noexcept(T::x);

template<typename T, typename U>
void f(T, U**) noexcept(T::y); // expected-error {{no member named 'y' in 'A'}}

template<typename T, typename U>
void f(T, U***) noexcept(T::x);

template<>
void f(A, int*) noexcept; // expected-note {{previous declaration is here}}

template<>
void f(A, int*); // expected-error {{'f<A, int>' is missing exception specification 'noexcept'}}

template<>
void f(A, int**) noexcept; // expected-error {{exception specification in declaration does not match previous declaration}}
// expected-note@-1 {{in instantiation of exception specification for 'f<A, int>' requested here}}
// expected-note@-2 {{previous declaration is here}}

// FIXME: Exception specification is currently set to EST_None if instantiation fails.
template<>
void f(A, int**);

template<>
void f(A, int***) noexcept; // expected-note {{previous declaration is here}}

template<>
void f(A, int***); // expected-error {{'f<A, int>' is missing exception specification 'noexcept'}}

}
87 changes: 87 additions & 0 deletions clang/test/ClangScanDeps/optimize-canonicalize-macros.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// This test verifies that command lines with equivalent -D and -U arguments
// are canonicalized to the same module variant.

// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands.json.in > %t/build/compile-commands.json
// RUN: clang-scan-deps -compilation-database %t/build/compile-commands.json \
// RUN: -j 1 -format experimental-full -optimize-args=canonicalize-macros > %t/deps.db
// RUN: cat %t/deps.db | FileCheck %s -DPREFIX=%/t

// Verify that there are only two variants and that the expected merges have
// happened.

// CHECK: {
// CHECK-NEXT: "modules": [
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file":
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "J=1"
// CHECK-NOT: "J"
// CHECK-NOT: "K"
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file":
// CHECK-NEXT: "command-line": [
// CHECK: "Fඞ"
// CHECK: 0D9E
// CHECK: "K"
// CHECK: "K"
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK: ]
// CHECK: }


//--- build/compile-commands.json.in

[
{
"directory": "DIR",
"command": "clang -c DIR/tu0.m -DJ=1 -UJ -DJ=2 -DI -DK(x)=x -I modules/A -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps",
"file": "DIR/tu0.m"
},
{
"directory": "DIR",
"command": "clang -c DIR/tu1.m -DK -DK(x)=x -DI -D \"J=2\" -I modules/A -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps",
"file": "DIR/tu1.m"
},
{
"directory": "DIR",
"command": "clang -c DIR/tu2.m -I modules/A -DFඞ \"-DF\\\\u{0D9E}\" -DK -DK -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps",
"file": "DIR/tu2.m"
}
]

//--- modules/A/module.modulemap

module A {
umbrella header "A.h"
}

//--- modules/A/A.h

//--- tu0.m

#include <A.h>

//--- tu1.m

#include <A.h>

//--- tu2.m

#include <A.h>
114 changes: 105 additions & 9 deletions clang/test/ClangScanDeps/optimize-vfs-pch.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
// RUN: split-file %s %t
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands-pch.json.in > %t/build/compile-commands-pch.json
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands-tu.json.in > %t/build/compile-commands-tu.json
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands-tu-no-vfs.json.in > %t/build/compile-commands-tu-no-vfs.json
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands-tu-no-vfs-error.json.in > %t/build/compile-commands-tu-no-vfs-error.json
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands-tu1.json.in > %t/build/compile-commands-tu1.json
// RUN: sed -e "s|DIR|%/t|g" %t/build/pch-overlay.yaml.in > %t/build/pch-overlay.yaml

// RUN: clang-scan-deps -compilation-database %t/build/compile-commands-pch.json \
Expand All @@ -23,11 +24,66 @@
// RUN: %clang @%t/C.rsp
// RUN: %clang @%t/tu.rsp

// RUN: not clang-scan-deps -compilation-database %t/build/compile-commands-tu-no-vfs.json \
// RUN: -j 1 -format experimental-full --optimize-args=vfs,header-search 2>&1 | FileCheck %s

// CHECK: error: PCH was compiled with different VFS overlay files than are currently in use
// CHECK: note: current translation unit has no VFS overlays
// RUN: not clang-scan-deps -compilation-database %t/build/compile-commands-tu-no-vfs-error.json \
// RUN: -j 1 -format experimental-full --optimize-args=vfs,header-search 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s

// CHECK-ERROR: error: PCH was compiled with different VFS overlay files than are currently in use
// CHECK-ERROR: note: current translation unit has no VFS overlays

// Next test is to verify that a module that doesn't use the VFS, that depends
// on the PCH's A, which does use the VFS, still records that it needs the VFS.
// This avoids a fatal error when emitting diagnostics.

// RUN: clang-scan-deps -compilation-database %t/build/compile-commands-tu1.json \
// RUN: -j 1 -format experimental-full --optimize-args=vfs,header-search > %t/tu1-deps.db
// RUN: %deps-to-rsp %t/tu1-deps.db --tu-index=0 > %t/tu1.rsp
// Reuse existing B
// RUN: %deps-to-rsp %t/tu1-deps.db --module-name=E > %t/E.rsp
// RUN: %deps-to-rsp %t/tu1-deps.db --module-name=D > %t/D.rsp
// The build of D depends on B which depend on the prebuilt A. D will only build
// if it has A's VFS, as it needs to emit a diagnostic showing the content of A.
// RUN: %clang @%t/E.rsp
// RUN: %clang @%t/D.rsp -verify
// RUN: %clang @%t/tu1.rsp
// RUN: cat %t/tu1-deps.db | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t

// Check that D has the overlay, but E doesn't.
// CHECK: {
// CHECK-NEXT: "modules": [
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "module-name": "E"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/modules/D/module.modulemap",
// CHECK-NEXT: "command-line": [
// CHECK: "-ivfsoverlay"
// CHECK-NEXT: "[[PREFIX]]/build/pch-overlay.yaml"
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "{{.*}}"
// CHECK-NEXT: "{{.*}}"
// CHECK-NEXT: "{{.*}}"
// CHECK-NEXT: "{{.*}}"
// CHECK-NEXT: ],
// CHECK: "name": "D"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/modules/E/module.modulemap",
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-ivfsoverlay"
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "{{.*}}"
// CHECK-NEXT: "{{.*}}"
// CHECK-NEXT: ],
// CHECK: "name": "E"
// CHECK-NEXT: }

//--- build/compile-commands-pch.json.in

Expand All @@ -49,16 +105,26 @@
}
]

//--- build/compile-commands-tu-no-vfs.json.in
//--- build/compile-commands-tu-no-vfs-error.json.in

[
{
"directory": "DIR",
"command": "clang -fsyntax-only DIR/tu.m -I DIR/modules/A -I DIR/modules/B -I DIR/modules/C -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o",
"command": "clang -Wpch-vfs-diff -Werror=pch-vfs-diff -fsyntax-only DIR/tu.m -I DIR/modules/A -I DIR/modules/B -I DIR/modules/C -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o",
"file": "DIR/tu.m"
}
]

//--- build/compile-commands-tu1.json.in

[
{
"directory": "DIR",
"command": "clang -fsyntax-only DIR/tu1.m -I DIR/modules/B -I DIR/modules/D -I DIR/modules/E -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu1.o -ivfsoverlay DIR/build/pch-overlay.yaml",
"file": "DIR/tu1.m"
}
]

//--- build/pch-overlay.yaml.in

{
Expand Down Expand Up @@ -95,7 +161,7 @@

//--- build/A.h

typedef int A_t;
typedef int A_t __attribute__((deprecated("yep, it's depr")));

//--- modules/B/module.modulemap

Expand Down Expand Up @@ -127,3 +193,33 @@
A_t a = 0;
B_t b = 0;
C_t c = 0;

//--- modules/D/module.modulemap

module D {
umbrella header "D.h"
export *
}

//--- modules/D/D.h
#include <B.h>
#include <E.h>

typedef A_t D_t; // expected-warning{{'A_t' is deprecated}}
// expected-note@*:* {{marked deprecated here}}

//--- modules/E/module.modulemap

module E {
umbrella header "E.h"
}

//--- modules/E/E.h
typedef int E_t;

//--- tu1.m

#include <D.h>

D_t d = 0;
E_t e = 0;
41 changes: 41 additions & 0 deletions clang/test/CodeGen/tbaa-struct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,38 @@ void copy7(A *a1, AA *a2) {
*a1 = *a2;
}

struct NamedBitfields {
signed f0 : 9;
unsigned f1 : 2;
char f2;
double f3;
};

void copy8(NamedBitfields *a1, NamedBitfields *a2) {
// CHECK-LABEL: _Z5copy8P14NamedBitfieldsS0_
// CHECK: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %a1, ptr noundef nonnull align 8 dereferenceable(16) %a2, i64 16, i1 false),
// CHECK-OLD-SAME: !tbaa.struct [[TS6:!.*]]
// CHECK-NEW-SAME: !tbaa [[TAG_NamedBitfields:!.+]], !tbaa.struct
*a1 = *a2;
}

struct NamedBitfields2 {
char a, b, c;
signed f0 : 3;
unsigned f1 : 4;
char f2 : 7;
double f3;
unsigned f4 : 4;
};

void copy9(NamedBitfields2 *a1, NamedBitfields2 *a2) {
// CHECK-LABEL: _Z5copy9P15NamedBitfields2S0_
// CHECK: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(24) %a1, ptr noundef nonnull align 8 dereferenceable(24) %a2, i64 24, i1 false),
// CHECK-OLD-SAME: !tbaa.struct [[TS7:!.*]]
// CHECK-NEW-SAME: !tbaa [[TAG_NamedBitfields2:!.+]], !tbaa.struct
*a1 = *a2;
}

// CHECK-OLD: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}}
// CHECK-OLD: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}}
// CHECK-OLD: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0}
Expand All @@ -113,6 +145,10 @@ void copy7(A *a1, AA *a2) {
// CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}}
// CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
// CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
// CHECK-OLD: [[TS6]] = !{i64 0, i64 4, [[TAG_INT]], i64 1, i64 4, [[TAG_INT]], i64 2, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE:!.+]]}
// CHECK-OLD: [[TAG_DOUBLE]] = !{[[DOUBLE:!.+]], [[DOUBLE]], i64 0}
// CHECK-OLD [[DOUBLE]] = !{!"double", [[CHAR]], i64 0}
// CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 4, [[TAG_INT]], i64 3, i64 4, [[TAG_INT]], i64 4, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 4, [[TAG_INT]]}

// CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
// CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}
Expand All @@ -127,3 +163,8 @@ void copy7(A *a1, AA *a2) {
// CHECK-NEW-DAG: [[TAG_C]] = !{[[TYPE_C]], [[TYPE_C]], i64 0, i64 3}
// CHECK-NEW-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS1D", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
// CHECK-NEW-DAG: [[TAG_D]] = !{[[TYPE_D]], [[TYPE_D]], i64 0, i64 6}
// CHECK-NEW-DAG: [[TAG_NamedBitfields]] = !{[[TYPE_NamedBitfields:!.+]], [[TYPE_NamedBitfields]], i64 0, i64 16}
// CHECK-NEW-DAG: [[TYPE_NamedBitfields]] = !{[[TYPE_char]], i64 16, !"_ZTS14NamedBitfields", [[TYPE_int]], i64 0, i64 4, [[TYPE_int]], i64 1, i64 4, [[TYPE_char]], i64 2, i64 1, [[TYPE_double:!.+]], i64 8, i64 8}
// CHECK-NEW-DAG: [[TYPE_double]] = !{[[TYPE_char]], i64 8, !"double"}
// CHECK-NEW-DAG: [[TAG_NamedBitfields2]] = !{[[TYPE_NamedBitfields2:!.+]], [[TYPE_NamedBitfields2]], i64 0, i64 24}
// CHECK-NEW-DAG: [[TYPE_NamedBitfields2]] = !{[[TYPE_char]], i64 24, !"_ZTS15NamedBitfields2", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1, [[TYPE_int]], i64 3, i64 4, [[TYPE_int]], i64 3, i64 4, [[TYPE_char]], i64 4, i64 1, [[TYPE_double]], i64 8, i64 8, [[TYPE_int]], i64 16, i64 4}
30 changes: 30 additions & 0 deletions clang/test/CodeGenHLSL/builtins/dot-builtin.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s

// CHECK-LABEL: builtin_bool_to_float_type_promotion
// CHECK: %conv1 = uitofp i1 %tobool to double
// CHECK: %dx.dot = fmul double %conv, %conv1
// CHECK: %conv2 = fptrunc double %dx.dot to float
// CHECK: ret float %conv2
float builtin_bool_to_float_type_promotion ( float p0, bool p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
}

// CHECK-LABEL: builtin_bool_to_float_arg1_type_promotion
// CHECK: %conv = uitofp i1 %tobool to double
// CHECK: %conv1 = fpext float %1 to double
// CHECK: %dx.dot = fmul double %conv, %conv1
// CHECK: %conv2 = fptrunc double %dx.dot to float
// CHECK: ret float %conv2
float builtin_bool_to_float_arg1_type_promotion ( bool p0, float p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
}

// CHECK-LABEL: builtin_dot_int_to_float_promotion
// CHECK: %conv = fpext float %0 to double
// CHECK: %conv1 = sitofp i32 %1 to double
// CHECK: dx.dot = fmul double %conv, %conv1
// CHECK: %conv2 = fptrunc double %dx.dot to float
// CHECK: ret float %conv2
float builtin_dot_int_to_float_promotion ( float p0, int p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
}
265 changes: 265 additions & 0 deletions clang/test/CodeGenHLSL/builtins/dot.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
// RUN: --check-prefixes=CHECK,NATIVE_HALF
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF

#ifdef __HLSL_ENABLE_16_BIT
// NATIVE_HALF: %dx.dot = mul i16 %0, %1
// NATIVE_HALF: ret i16 %dx.dot
int16_t test_dot_short ( int16_t p0, int16_t p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v2i16(<2 x i16> %0, <2 x i16> %1)
// NATIVE_HALF: ret i16 %dx.dot
int16_t test_dot_short2 ( int16_t2 p0, int16_t2 p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v3i16(<3 x i16> %0, <3 x i16> %1)
// NATIVE_HALF: ret i16 %dx.dot
int16_t test_dot_short3 ( int16_t3 p0, int16_t3 p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v4i16(<4 x i16> %0, <4 x i16> %1)
// NATIVE_HALF: ret i16 %dx.dot
int16_t test_dot_short4 ( int16_t4 p0, int16_t4 p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = mul i16 %0, %1
// NATIVE_HALF: ret i16 %dx.dot
uint16_t test_dot_ushort ( uint16_t p0, uint16_t p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v2i16(<2 x i16> %0, <2 x i16> %1)
// NATIVE_HALF: ret i16 %dx.dot
uint16_t test_dot_ushort2 ( uint16_t2 p0, uint16_t2 p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v3i16(<3 x i16> %0, <3 x i16> %1)
// NATIVE_HALF: ret i16 %dx.dot
uint16_t test_dot_ushort3 ( uint16_t3 p0, uint16_t3 p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v4i16(<4 x i16> %0, <4 x i16> %1)
// NATIVE_HALF: ret i16 %dx.dot
uint16_t test_dot_ushort4 ( uint16_t4 p0, uint16_t4 p1 ) {
return dot ( p0, p1 );
}
#endif

// CHECK: %dx.dot = mul i32 %0, %1
// CHECK: ret i32 %dx.dot
int test_dot_int ( int p0, int p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i32 @llvm.dx.dot.v2i32(<2 x i32> %0, <2 x i32> %1)
// CHECK: ret i32 %dx.dot
int test_dot_int2 ( int2 p0, int2 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i32 @llvm.dx.dot.v3i32(<3 x i32> %0, <3 x i32> %1)
// CHECK: ret i32 %dx.dot
int test_dot_int3 ( int3 p0, int3 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i32 @llvm.dx.dot.v4i32(<4 x i32> %0, <4 x i32> %1)
// CHECK: ret i32 %dx.dot
int test_dot_int4 ( int4 p0, int4 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = mul i32 %0, %1
// CHECK: ret i32 %dx.dot
uint test_dot_uint ( uint p0, uint p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i32 @llvm.dx.dot.v2i32(<2 x i32> %0, <2 x i32> %1)
// CHECK: ret i32 %dx.dot
uint test_dot_uint2 ( uint2 p0, uint2 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i32 @llvm.dx.dot.v3i32(<3 x i32> %0, <3 x i32> %1)
// CHECK: ret i32 %dx.dot
uint test_dot_uint3 ( uint3 p0, uint3 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i32 @llvm.dx.dot.v4i32(<4 x i32> %0, <4 x i32> %1)
// CHECK: ret i32 %dx.dot
uint test_dot_uint4 ( uint4 p0, uint4 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = mul i64 %0, %1
// CHECK: ret i64 %dx.dot
int64_t test_dot_long ( int64_t p0, int64_t p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i64 @llvm.dx.dot.v2i64(<2 x i64> %0, <2 x i64> %1)
// CHECK: ret i64 %dx.dot
int64_t test_dot_long2 ( int64_t2 p0, int64_t2 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i64 @llvm.dx.dot.v3i64(<3 x i64> %0, <3 x i64> %1)
// CHECK: ret i64 %dx.dot
int64_t test_dot_long3 ( int64_t3 p0, int64_t3 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i64 @llvm.dx.dot.v4i64(<4 x i64> %0, <4 x i64> %1)
// CHECK: ret i64 %dx.dot
int64_t test_dot_long4 ( int64_t4 p0, int64_t4 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = mul i64 %0, %1
// CHECK: ret i64 %dx.dot
uint64_t test_dot_ulong ( uint64_t p0, uint64_t p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i64 @llvm.dx.dot.v2i64(<2 x i64> %0, <2 x i64> %1)
// CHECK: ret i64 %dx.dot
uint64_t test_dot_ulong2 ( uint64_t2 p0, uint64_t2 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i64 @llvm.dx.dot.v3i64(<3 x i64> %0, <3 x i64> %1)
// CHECK: ret i64 %dx.dot
uint64_t test_dot_ulong3 ( uint64_t3 p0, uint64_t3 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call i64 @llvm.dx.dot.v4i64(<4 x i64> %0, <4 x i64> %1)
// CHECK: ret i64 %dx.dot
uint64_t test_dot_ulong4 ( uint64_t4 p0, uint64_t4 p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = fmul half %0, %1
// NATIVE_HALF: ret half %dx.dot
// NO_HALF: %dx.dot = fmul float %0, %1
// NO_HALF: ret float %dx.dot
half test_dot_half ( half p0, half p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v2f16(<2 x half> %0, <2 x half> %1)
// NATIVE_HALF: ret half %dx.dot
// NO_HALF: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %1)
// NO_HALF: ret float %dx.dot
half test_dot_half2 ( half2 p0, half2 p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v3f16(<3 x half> %0, <3 x half> %1)
// NATIVE_HALF: ret half %dx.dot
// NO_HALF: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %1)
// NO_HALF: ret float %dx.dot
half test_dot_half3 ( half3 p0, half3 p1 ) {
return dot ( p0, p1 );
}

// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v4f16(<4 x half> %0, <4 x half> %1)
// NATIVE_HALF: ret half %dx.dot
// NO_HALF: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %0, <4 x float> %1)
// NO_HALF: ret float %dx.dot
half test_dot_half4 ( half4 p0, half4 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = fmul float %0, %1
// CHECK: ret float %dx.dot
float test_dot_float ( float p0, float p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %1)
// CHECK: ret float %dx.dot
float test_dot_float2 ( float2 p0, float2 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %1)
// CHECK: ret float %dx.dot
float test_dot_float3 ( float3 p0, float3 p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %0, <4 x float> %1)
// CHECK: ret float %dx.dot
float test_dot_float4 ( float4 p0, float4 p1) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %splat.splat, <2 x float> %1)
// CHECK: ret float %dx.dot
float test_dot_float2_splat ( float p0, float2 p1 ) {
return dot( p0, p1 );
}

// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %splat.splat, <3 x float> %1)
// CHECK: ret float %dx.dot
float test_dot_float3_splat ( float p0, float3 p1 ) {
return dot( p0, p1 );
}

// CHECK: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %splat.splat, <4 x float> %1)
// CHECK: ret float %dx.dot
float test_dot_float4_splat ( float p0, float4 p1 ) {
return dot( p0, p1 );
}

// CHECK: %conv = sitofp i32 %1 to float
// CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0
// CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer
// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %splat.splat)
// CHECK: ret float %dx.dot
float test_builtin_dot_float2_int_splat ( float2 p0, int p1 ) {
return dot ( p0, p1 );
}

// CHECK: %conv = sitofp i32 %1 to float
// CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0
// CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer
// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %splat.splat)
// CHECK: ret float %dx.dot
float test_builtin_dot_float3_int_splat ( float3 p0, int p1 ) {
return dot ( p0, p1 );
}

// CHECK: %dx.dot = fmul double %0, %1
// CHECK: ret double %dx.dot
double test_dot_double ( double p0, double p1 ) {
return dot ( p0, p1 );
}

// CHECK: %conv = zext i1 %tobool to i32
// CHECK: %dx.dot = mul i32 %conv, %1
// CHECK: ret i32 %dx.dot
int test_dot_bool_scalar_arg0_type_promotion ( bool p0, int p1 ) {
return dot ( p0, p1 );
}

// CHECK: %conv = zext i1 %tobool to i32
// CHECK: %dx.dot = mul i32 %0, %conv
// CHECK: ret i32 %dx.dot
int test_dot_bool_scalar_arg1_type_promotion ( int p0, bool p1 ) {
return dot ( p0, p1 );
}
171 changes: 88 additions & 83 deletions clang/test/CodeGenSYCL/address-space-conversions.cpp

Large diffs are not rendered by default.

128 changes: 128 additions & 0 deletions clang/test/CodeGenSYCL/amd-address-space-conversions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
void bar(int &Data) {}
// CHECK: define dso_local void @[[RAW_REF:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) %
void bar2(int &Data) {}
// CHECK: define dso_local void @[[RAW_REF2:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) %
void bar(__attribute__((opencl_local)) int &Data) {}
// CHECK: define dso_local void @[[LOCAL_REF:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef align 4 dereferenceable(4) %
void foo(int *Data) {}
// CHECK: define dso_local void @[[RAW_PTR:[a-zA-Z0-9_]+]](ptr noundef %
void foo2(int *Data) {}
// CHECK: define dso_local void @[[RAW_PTR2:[a-zA-Z0-9_]+]](ptr noundef %
void foo(__attribute__((opencl_local)) int *Data) {}
// CHECK: define dso_local void @[[LOC_PTR:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef %

template <typename T>
void tmpl(T t);
// See Check Lines below.

void usages() {
int *NoAS;
// CHECK: [[NoAS:%[a-zA-Z0-9]+]] = alloca ptr, align 8, addrspace(5)
__attribute__((opencl_global)) int *GLOB;
// CHECK: [[GLOB:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5)
__attribute__((opencl_local)) int *LOC;
// CHECK: [[LOC:%[a-zA-Z0-9]+]] = alloca ptr addrspace(3), align 4, addrspace(5)
__attribute__((opencl_private)) int *PRIV;
// CHECK: [[PRIV:%[a-zA-Z0-9]+]] = alloca ptr addrspace(5), align 4, addrspace(5)
__attribute__((opencl_global_device)) int *GLOBDEVICE;
// CHECK: [[GLOB_DEVICE:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5)
__attribute__((opencl_global_host)) int *GLOBHOST;
// CHECK: [[GLOB_HOST:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5)
LOC = nullptr;
// CHECK: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr [[LOC]].ascast, align 4
GLOB = nullptr;
// CHECK: store ptr addrspace(1) null, ptr [[GLOB]].ascast, align 8
NoAS = (int *)GLOB;
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: store ptr [[GLOB_CAST]], ptr [[NoAS]].ascast, align 8
NoAS = (int *)LOC;
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD]] to ptr
// CHECK: store ptr [[LOC_CAST]], ptr [[NoAS]].ascast, align 8
NoAS = (int *)PRIV;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(5), ptr [[PRIV]].ascast, align 4
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(5) [[NoAS_LOAD]] to ptr
// CHECK: store ptr %5, ptr [[NoAS]].ascast, align 8
GLOB = (__attribute__((opencl_global)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr %6 to ptr addrspace(1)
// CHECK: store ptr addrspace(1) %7, ptr [[GLOB]].ascast, align 8
LOC = (__attribute__((opencl_local)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(3)
// CHECK: store ptr addrspace(3) %9, ptr [[LOC]].ascast, align 4
PRIV = (__attribute__((opencl_private)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(5)
// CHECK: store ptr addrspace(5) [[NoAS_CAST]], ptr [[PRIV]].ascast, align 4
GLOB = (__attribute__((opencl_global)) int *)GLOBDEVICE;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]]DEVICE.ascast, align 8
// CHECK: store ptr addrspace(1) [[NoAS_LOAD]], ptr [[GLOB]].ascast, align 8
GLOB = (__attribute__((opencl_global)) int *)GLOBHOST;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]]HOST.ascast, align 8
// CHECK: tore ptr addrspace(1) [[NoAS_LOAD]], ptr [[GLOB]].ascast, align 8
bar(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]])
bar2(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]])
bar(*LOC);
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: call void @_Z3barRU3AS3i(ptr addrspace(3) noundef align 4 dereferenceable(4) [[LOC_LOAD]])
bar2(*LOC);
// CHECK: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD2]] to ptr
// CHECK: call void @_Z4bar2Ri(ptr noundef nonnull align 4 dereferenceable(4) [[LOC_CAST2]])
bar(*NoAS);
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @_Z3barRi(ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD]])
bar2(*NoAS);
// CHECK: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @_Z4bar2Ri(ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD2]])
foo(GLOB);
// CHECK: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD3]] to ptr
// CHECK: call void @[[RAW_PTR]](ptr noundef [[GLOB_CAST3]])
foo2(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD4]] to ptr
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[GLOB_CAST4]])
foo(LOC);
// CHECK: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: call void @[[LOC_PTR]](ptr addrspace(3) noundef [[LOC_LOAD3]])
foo2(LOC);
// CHECK: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD4]] to ptr
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[LOC_CAST4]])
foo(NoAS);
// CHECK: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @[[RAW_PTR]](ptr noundef [[NoAS_LOAD3]])
foo2(NoAS);
// CHECK: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[NoAS_LOAD4]])

// Ensure that we still get 3 different template instantiations.
tmpl(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: call void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef [[GLOB_LOAD4]])
tmpl(LOC);
// CHECK: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: call void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef [[LOC_LOAD5]])
tmpl(PRIV);
// CHECK: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(5), ptr [[PRIV]].ascast, align 4
// CHECK: call void @_Z4tmplIPU3AS5iEvT_(ptr addrspace(5) noundef [[PRIV_LOAD5]])
tmpl(NoAS);
// CHECK: [[NoAS_LOAD5:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @_Z4tmplIPiEvT_(ptr noundef [[NoAS_LOAD5]])
}

// CHECK: declare void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef)
// CHECK: declare void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef)
// CHECK: declare void @_Z4tmplIPU3AS5iEvT_(ptr addrspace(5) noundef)
// CHECK: declare void @_Z4tmplIPiEvT_(ptr noundef)

122 changes: 122 additions & 0 deletions clang/test/CodeGenSYCL/cuda-address-space-conversions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
void bar(int &Data) {}
// CHECK: define dso_local void @[[RAW_REF:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) %
void bar2(int &Data) {}
// CHECK: define dso_local void @[[RAW_REF2:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) %
void bar(__attribute__((opencl_local)) int &Data) {}
// CHECK: define dso_local void @[[LOCAL_REF:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef align 4 dereferenceable(4) %
void foo(int *Data) {}
// CHECK: define dso_local void @[[RAW_PTR:[a-zA-Z0-9_]+]](ptr noundef %
void foo2(int *Data) {}
// CHECK: define dso_local void @[[RAW_PTR2:[a-zA-Z0-9_]+]](ptr noundef %
void foo(__attribute__((opencl_local)) int *Data) {}
// CHECK: define dso_local void @[[LOC_PTR:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef %

template <typename T>
void tmpl(T t);
// See Check Lines below.

void usages() {
int *NoAS;
// CHECK: [[NoAS:%[a-zA-Z0-9]+]] = alloca ptr, align 8
__attribute__((opencl_global)) int *GLOB;
// CHECK: [[GLOB:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8
__attribute__((opencl_local)) int *LOC;
// CHECK: [[LOC:%[a-zA-Z0-9]+]] = alloca ptr addrspace(3), align 8
__attribute__((opencl_private)) int *PRIV;
// CHECK: [[PRIV:%[a-zA-Z0-9]+]] = alloca ptr, align 8
__attribute__((opencl_global_device)) int *GLOBDEVICE;
// CHECK: [[GLOB_DEVICE:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8
__attribute__((opencl_global_host)) int *GLOBHOST;
// CHECK: [[GLOB_HOST:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8
LOC = nullptr;
// CHECK: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr [[LOC]], align 8
GLOB = nullptr;
// CHECK: store ptr addrspace(1) null, ptr [[GLOB]], align 8
NoAS = (int *)GLOB;
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: store ptr [[GLOB_CAST]], ptr [[NoAS]], align 8
NoAS = (int *)LOC;
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD]] to ptr
// CHECK: store ptr [[LOC_CAST]], ptr [[NoAS]], align 8
NoAS = (int *)PRIV;
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[PRIV]], align 8
// CHECK: store ptr [[LOC_LOAD]], ptr [[NoAS]], align 8
GLOB = (__attribute__((opencl_global)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(1)
// CHECK: store ptr addrspace(1) [[NoAS_CAST]], ptr [[GLOB]], align 8
LOC = (__attribute__((opencl_local)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(3)
// CHECK: store ptr addrspace(3) [[NoAS_CAST]], ptr [[LOC]], align 8
PRIV = (__attribute__((opencl_private)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: store ptr [[NoAS_LOAD]], ptr [[PRIV]], align 8
GLOB = (__attribute__((opencl_global)) int *)GLOBDEVICE;
// CHECK: [[GLOBDEVICE_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB_DEVICE]], align 8
// CHECK: store ptr addrspace(1) [[GLOBDEVICE_LOAD]], ptr %GLOB, align 8
GLOB = (__attribute__((opencl_global)) int *)GLOBHOST;
// CHECK: [[GLOB_HOST_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB_HOST]], align 8
// CHECK: store ptr addrspace(1) [[GLOB_HOST_LOAD]], ptr [[GLOB]], align 8
bar(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]])
bar2(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]])
bar(*LOC);
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: call void @[[LOCAL_REF]](ptr addrspace(3) noundef align 4 dereferenceable(4) [[LOC_LOAD]])
bar2(*LOC);
// CHECK: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD2]] to ptr
// CHECK: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[LOC_CAST2]])
bar(*NoAS);
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD]])
bar2(*NoAS);
// CHECK: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD2]])
foo(GLOB);
// CHECK: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD3]] to ptr
// CHECK: call void @[[RAW_PTR]](ptr noundef [[GLOB_CAST3]])
foo2(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD4]] to ptr
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[GLOB_CAST4]])
foo(LOC);
// CHECK: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: call void @[[LOC_PTR]](ptr addrspace(3) noundef [[LOC_LOAD3]])
foo2(LOC);
// CHECK: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD4]] to ptr
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[LOC_CAST4]])
foo(NoAS);
// CHECK: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: call void @[[RAW_PTR]](ptr noundef [[NoAS_LOAD3]])
foo2(NoAS);
// CHECK: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[NoAS_LOAD4]])
tmpl(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: call void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef [[GLOB_LOAD4]])
tmpl(LOC);
// CHECK: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: call void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef [[LOC_LOAD5]])
tmpl(PRIV);
// CHECK: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load ptr, ptr [[PRIV]], align 8
// CHECK: call void @_Z4tmplIPiEvT_(ptr noundef [[PRIV_LOAD5]])
tmpl(NoAS);
// CHECK: %33 = load ptr, ptr %NoAS, align 8
// CHECK: call void @_Z4tmplIPiEvT_(ptr noundef %33)
}

// CHECK: declare void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef)
// CHECK: declare void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef)
// CHECK: declare void @_Z4tmplIPiEvT_(ptr noundef)
9 changes: 8 additions & 1 deletion clang/test/Driver/gpu-libc-headers.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@
// CHECK-HEADERS: "-cc1"{{.*}}"-internal-isystem" "{{.*}}include{{.*}}llvm_libc_wrappers"{{.*}}"-isysroot" "./"
// CHECK-HEADERS: "-cc1"{{.*}}"-internal-isystem" "{{.*}}include{{.*}}llvm_libc_wrappers"{{.*}}"-isysroot" "./"

// RUN: %clang -### --target=amdgcn-amd-amdhsa -mcpu=gfx90a --sysroot=./ \
// RUN: -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-HEADERS-AMDGPU
// RUN: %clang -### --target=nvptx64-nvidia-cuda -march=sm_89 --sysroot=./ \
// RUN: -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-HEADERS-NVPTX
// CHECK-HEADERS-AMDGPU: "-cc1"{{.*}}"-internal-isystem" "{{.*}}include{{.*}}amdgcn-amd-amdhsa"{{.*}}"-isysroot" "./"
// CHECK-HEADERS-NVPTX: "-cc1"{{.*}}"-internal-isystem" "{{.*}}include{{.*}}nvptx64-nvidia-cuda"{{.*}}"-isysroot" "./"

// RUN: %clang -### --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -nogpulib \
// RUN: -nogpuinc %s 2>&1 | FileCheck %s --check-prefix=CHECK-HEADERS-DISABLED
// RUN: %clang -### --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -nogpulib \
// RUN: -nostdinc %s 2>&1 | FileCheck %s --check-prefix=CHECK-HEADERS-DISABLED
// RUN: %clang -### --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -nogpulib \
// RUN: -nobuiltininc %s 2>&1 | FileCheck %s --check-prefix=CHECK-HEADERS-DISABLED
// CHECK-HEADERS-DISABLED-NOT: "-cc1"{{.*}}"-c-isystem" "{{.*}}include{{.*}}gpu-none-llvm"
// CHECK-HEADERS-DISABLED-NOT: "-cc1"{{.*}}"-internal-isystem" "{{.*}}include{{.*}}gpu-none-llvm"
5 changes: 3 additions & 2 deletions clang/test/Driver/print-multi-selection-flags.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@
// CHECK-M85_NO_FP_DP: -mfpu=fp-armv8-fullfp16-sp-d16

// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf -march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s
// CHECK-LSE: -march=aarch64{{.*}}+lse{{.*}}
// CHECK-LSE: --target=aarch64-none-unknown-elf
// CHECK-LSE: -march=armv8-a{{.*}}+lse{{.*}}

// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf -march=armv8.5-a+sve+sve2 | FileCheck --check-prefix=CHECK-SVE2 %s
// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf -march=armv9-a | FileCheck --check-prefix=CHECK-SVE2 %s
// CHECK-SVE2: --target=aarch64-none-unknown-elf
// CHECK-SVE2: -march=aarch64{{.*}}+simd{{.*}}+sve{{.*}}+sve2{{.*}}
// CHECK-SVE2: -march=armv{{.*}}-a{{.*}}+simd{{.*}}+sve{{.*}}+sve2{{.*}}
8 changes: 2 additions & 6 deletions clang/test/Profile/c-mcdc-class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@ Value::~Value(void) {
// UPDATE FINAL BITMASK WITH RESULT.
// MCDCCTOR-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCCTOR: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDCCTOR: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDCCTOR: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm__ZN5ValueC2Ev to i64), %[[LAB2]]
// MCDCCTOR: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDCCTOR: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm__ZN5ValueC2Ev, i32 %[[LAB1]]
// MCDCCTOR: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDCCTOR: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDCCTOR: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand Down Expand Up @@ -93,9 +91,7 @@ Value::~Value(void) {
// UPDATE FINAL BITMASK WITH RESULT.
// MCDCDTOR-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCDTOR: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDCDTOR: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDCDTOR: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm__ZN5ValueD2Ev to i64), %[[LAB2]]
// MCDCDTOR: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDCDTOR: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm__ZN5ValueD2Ev, i32 %[[LAB1]]
// MCDCDTOR: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDCDTOR: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDCDTOR: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand Down
16 changes: 4 additions & 12 deletions clang/test/Profile/c-mcdc-logicalop-ternary.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ int test(int a, int b, int c, int d, int e, int f) {
// MCDC-LABEL: cond.true:
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDC: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
// MCDC: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand All @@ -38,9 +36,7 @@ int test(int a, int b, int c, int d, int e, int f) {
// MCDC-LABEL: land.end:
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDC: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr getelementptr inbounds ([3 x i8], ptr @__profbm_test, i32 0, i32 1) to i64), %[[LAB2]]
// MCDC: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr getelementptr inbounds ([3 x i8], ptr @__profbm_test, i32 0, i32 1), i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand All @@ -52,9 +48,7 @@ int test(int a, int b, int c, int d, int e, int f) {
// MCDC-LABEL: cond.false:
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDC: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
// MCDC: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand All @@ -70,9 +64,7 @@ int test(int a, int b, int c, int d, int e, int f) {
// MCDC-LABEL: lor.end:
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDC: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr getelementptr inbounds ([3 x i8], ptr @__profbm_test, i32 0, i32 2) to i64), %[[LAB2]]
// MCDC: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr getelementptr inbounds ([3 x i8], ptr @__profbm_test, i32 0, i32 2), i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand Down
4 changes: 1 addition & 3 deletions clang/test/Profile/c-mcdc-nested-ternary.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ int test(int b, int c, int d, int e, int f) {
// UPDATE FINAL BITMASK WITH RESULT.
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDC: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
// MCDC: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand Down
4 changes: 1 addition & 3 deletions clang/test/Profile/c-mcdc-not.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,7 @@ int test(int a, int b, int c, int d, int e, int f) {
// UPDATE FINAL BITMASK WITH RESULT.
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDC: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
// MCDC: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand Down
4 changes: 1 addition & 3 deletions clang/test/Profile/c-mcdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ int test(int a, int b, int c, int d, int e, int f) {
// NOPROFPASS: call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 8, i32 0, ptr %mcdc.addr)
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
// MCDC: %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
// MCDC: %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
Expand Down
1 change: 1 addition & 0 deletions clang/test/Sema/attr-nonnull.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -verify -fsyntax-only
// RUN: %clang_cc1 %s -verify -fsyntax-only -fexperimental-new-constant-interpreter

void f1(int *a1, int *a2, int *a3, int *a4, int *a5, int *a6, int *a7,
int *a8, int *a9, int *a10, int *a11, int *a12, int *a13, int *a14,
Expand Down
3 changes: 2 additions & 1 deletion clang/test/SemaCXX/attr-nonnull.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter
struct S {
S(const char *) __attribute__((nonnull(2)));

Expand Down Expand Up @@ -84,4 +85,4 @@ constexpr int i4 = f4(&c, 0, 0); //expected-error {{constant expression}} expect
constexpr int i42 = f4(0, &c, 1); //expected-error {{constant expression}} expected-note {{null passed}}
constexpr int i43 = f4(&c, &c, 0);

}
}
1 change: 1 addition & 0 deletions clang/test/SemaCXX/compare-modules-cxx2a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// RUN: mkdir -p %t

// RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -verify -std=c++2a -fmodules -fmodules-cache-path=%t.mcp -I%S/Inputs %s -fno-modules-error-recovery -fmodule-map-file=%S/Inputs/compare.modulemap
// RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -verify -std=c++2a -fmodules -fmodules-cache-path=%t.mcp -I%S/Inputs %s -fno-modules-error-recovery -fmodule-map-file=%S/Inputs/compare.modulemap -fexperimental-new-constant-interpreter

struct CC { CC(...); };

Expand Down
5 changes: 5 additions & 0 deletions clang/test/SemaCXX/cxx1z-lambda-star-this.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING

// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -emit-llvm-only %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING -fexperimental-new-constant-interpreter

template <class, class>
constexpr bool is_same = false;
template <class T>
Expand Down
109 changes: 109 additions & 0 deletions clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected

float test_no_second_arg ( float2 p0) {
return __builtin_hlsl_dot ( p0 );
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
}

float test_too_many_arg ( float2 p0) {
return __builtin_hlsl_dot ( p0, p0, p0 );
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
}

float test_dot_no_second_arg ( float2 p0) {
return dot ( p0 );
// expected-error@-1 {{no matching function for call to 'dot'}}
}

float test_dot_vector_size_mismatch ( float3 p0, float2 p1 ) {
return dot ( p0, p1 );
// expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'float __attribute__((ext_vector_type(2)))' (vector of 2 'float' values)}}
}

float test_dot_builtin_vector_size_mismatch ( float3 p0, float2 p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
}

float test_dot_scalar_mismatch ( float p0, int p1 ) {
return dot ( p0, p1 );
// expected-error@-1 {{call to 'dot' is ambiguous}}
}

float test_dot_element_type_mismatch ( int2 p0, float2 p1 ) {
return dot ( p0, p1 );
// expected-error@-1 {{call to 'dot' is ambiguous}}
}

//NOTE: for all the *_promotion we are intentionally not handling type promotion in builtins
float test_builtin_dot_vec_int_to_float_promotion ( int2 p0, float2 p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
}

int64_t test_builtin_dot_vec_int_to_int64_promotion( int64_t2 p0, int2 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
}

float test_builtin_dot_vec_half_to_float_promotion( float2 p0, half2 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
}

#ifdef __HLSL_ENABLE_16_BIT
float test_builtin_dot_vec_int16_to_float_promotion( float2 p0, int16_t2 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
}

half test_builtin_dot_vec_int16_to_half_promotion( half2 p0, int16_t2 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
}

int test_builtin_dot_vec_int16_to_int_promotion( int2 p0, int16_t2 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
}

int64_t test_builtin_dot_vec_int16_to_int64_promotion( int64_t2 p0, int16_t2 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
}
#endif

float test_builtin_dot_float2_splat ( float p0, float2 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
}

float test_builtin_dot_float3_splat ( float p0, float3 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
}

float test_builtin_dot_float4_splat ( float p0, float4 p1 ) {
return __builtin_hlsl_dot( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
}

float test_dot_float2_int_splat ( float2 p0, int p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
}

float test_dot_float3_int_splat ( float3 p0, int p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
}

float test_builtin_dot_int_vect_to_float_vec_promotion ( int2 p0, float p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
// expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
}

int test_builtin_dot_bool_type_promotion ( bool p0, bool p1 ) {
return __builtin_hlsl_dot ( p0, p1 );
// expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}}
}
40 changes: 40 additions & 0 deletions clang/test/SemaHLSL/OverloadResolutionBugs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,46 @@ void Call4(int16_t H) {
Fn4(H);
}

int test_builtin_dot_bool_type_promotion ( bool p0, bool p1 ) {
return dot ( p0, p1 );
}

float test_dot_scalar_mismatch ( float p0, int p1 ) {
return dot ( p0, p1 );
}

float test_dot_element_type_mismatch ( int2 p0, float2 p1 ) {
return dot ( p0, p1 );
}

float test_builtin_dot_vec_int_to_float_promotion ( int2 p0, float2 p1 ) {
return dot ( p0, p1 );
}

int64_t test_builtin_dot_vec_int_to_int64_promotion( int64_t2 p0, int2 p1 ) {
return dot ( p0, p1 );
}

float test_builtin_dot_vec_half_to_float_promotion( float2 p0, half2 p1 ) {
return dot( p0, p1 );
}

float test_builtin_dot_vec_int16_to_float_promotion( float2 p0, int16_t2 p1 ) {
return dot( p0, p1 );
}

half test_builtin_dot_vec_int16_to_half_promotion( half2 p0, int16_t2 p1 ) {
return dot( p0, p1 );
}

int test_builtin_dot_vec_int16_to_int_promotion( int2 p0, int16_t2 p1 ) {
return dot( p0, p1 );
}

int64_t test_builtin_dot_vec_int16_to_int64_promotion( int64_t2 p0, int16_t2 p1 ) {
return dot( p0, p1 );
}

// https://github.com/llvm/llvm-project/issues/81049

// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
Expand Down
20 changes: 20 additions & 0 deletions clang/test/SemaOpenACC/no-branch-in-out.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,23 @@ void BreakContinue() {

}

void Return() {
#pragma acc parallel
{
return;// expected-error{{invalid return out of OpenACC Compute Construct}}
}

#pragma acc parallel
{
{
return;// expected-error{{invalid return out of OpenACC Compute Construct}}
}
}

#pragma acc parallel
{
for (int i = 0; i < 5; ++i) {
return;// expected-error{{invalid return out of OpenACC Compute Construct}}
}
}
}
17 changes: 17 additions & 0 deletions clang/test/SemaOpenACC/no-branch-in-out.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_cc1 %s -verify -fopenacc -fcxx-exceptions


void ReturnTest() {
#pragma acc parallel
{
(void)[]() { return; };
}

#pragma acc parallel
{
try {}
catch(...){
return; // expected-error{{invalid return out of OpenACC Compute Construct}}
}
}
}
14 changes: 1 addition & 13 deletions clang/test/SemaTemplate/class-template-noexcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
// RUN: %clang_cc1 -std=c++17 -verify %s
// RUN: %clang_cc1 -std=c++1z -verify %s
#if __cplusplus >= 201703
// expected-no-diagnostics
#endif

class A {
public:
static const char X;
Expand All @@ -14,19 +12,9 @@ const char A::X = 0;
template<typename U> void func() noexcept(U::X);

template<class... B, char x>
#if __cplusplus >= 201703
void foo(void(B...) noexcept(x)) {}
#else
void foo(void(B...) noexcept(x)) {} // expected-note{{candidate template ignored}}
#endif

void bar()
{
#if __cplusplus >= 201703
foo(func<A>);
#else
foo(func<A>); // expected-error{{no matching function for call}}
#endif
}


1 change: 1 addition & 0 deletions clang/tools/clang-scan-deps/ClangScanDeps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ static void ParseArgs(int argc, char **argv) {
.Case("header-search", ScanningOptimizations::HeaderSearch)
.Case("system-warnings", ScanningOptimizations::SystemWarnings)
.Case("vfs", ScanningOptimizations::VFS)
.Case("canonicalize-macros", ScanningOptimizations::Macros)
.Case("all", ScanningOptimizations::All)
.Default(std::nullopt);
if (!Optimization) {
Expand Down
19 changes: 0 additions & 19 deletions clang/unittests/Analysis/FlowSensitive/TestingSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,6 @@ llvm::Error checkDataflowWithNoopAnalysis(
{});

/// Returns the `ValueDecl` for the given identifier.
/// The returned pointer is guaranteed to be non-null; the function asserts if
/// no `ValueDecl` with the given name is found.
///
/// Requirements:
///
Expand Down Expand Up @@ -477,15 +475,6 @@ ValueT &getValueForDecl(ASTContext &ASTCtx, const Environment &Env,
return *cast<ValueT>(Env.getValue(*VD));
}

/// Returns the storage location for the field called `Name` of `Loc`.
/// Optionally casts the field storage location to `T`.
template <typename T = StorageLocation>
std::enable_if_t<std::is_base_of_v<StorageLocation, T>, T &>
getFieldLoc(const RecordStorageLocation &Loc, llvm::StringRef Name,
ASTContext &ASTCtx) {
return *cast<T>(Loc.getChild(*findValueDecl(ASTCtx, Name)));
}

/// Returns the value of a `Field` on the record referenced by `Loc.`
/// Returns null if `Loc` is null.
inline Value *getFieldValue(const RecordStorageLocation *Loc,
Expand All @@ -498,14 +487,6 @@ inline Value *getFieldValue(const RecordStorageLocation *Loc,
return Env.getValue(*FieldLoc);
}

/// Returns the value of a `Field` on the record referenced by `Loc.`
/// Returns null if `Loc` is null.
inline Value *getFieldValue(const RecordStorageLocation *Loc,
llvm::StringRef Name, ASTContext &ASTCtx,
const Environment &Env) {
return getFieldValue(Loc, *findValueDecl(ASTCtx, Name), Env);
}

/// Creates and owns constraints which are boolean values.
class ConstraintContext {
unsigned NextAtom = 0;
Expand Down
31 changes: 18 additions & 13 deletions clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2367,6 +2367,21 @@ TEST(TransferTest, InitListExprAsXValue) {
});
}

TEST(TransferTest, ArrayInitListExprOneRecordElement) {
// This is a crash repro.
std::string Code = R"cc(
struct S {};
void target() { S foo[] = {S()}; }
)cc";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
// Just verify that it doesn't crash.
});
}

TEST(TransferTest, InitListExprAsUnion) {
// This is a crash repro.
std::string Code = R"cc(
Expand All @@ -2377,24 +2392,14 @@ TEST(TransferTest, InitListExprAsUnion) {
} F;
public:
constexpr target() : F{nullptr} {
int *null = nullptr;
F.b; // Make sure we reference 'b' so it is modeled.
// [[p]]
}
constexpr target() : F{nullptr} {}
};
)cc";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");

auto &FLoc = getFieldLoc<RecordStorageLocation>(
*Env.getThisPointeeStorageLocation(), "F", ASTCtx);
auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
ASSERT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
ASSERT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
// Just verify that it doesn't crash.
});
}

Expand Down Expand Up @@ -3424,7 +3429,7 @@ TEST(TransferTest, AggregateInitializationFunctionPointer) {
struct S {
void (*const Field)();
};
void target() {
S s{nullptr};
}
Expand Down
2 changes: 1 addition & 1 deletion clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21669,7 +21669,7 @@ TEST_F(FormatTest, BreakPenaltyAfterCastLParen) {
" int)aaaaaaaaaaaaaaaaaaaaaaaa);",

Style);
Style.PenaltyBreakOpenParenthesis = 100000;
Style.PenaltyBreakOpenParenthesis = 100'000;
verifyFormat("foo((int)\n"
" aaaaaaaaaaaaaaaaaaaaaaaa);",
"foo((\n"
Expand Down
21 changes: 21 additions & 0 deletions clang/unittests/Format/FormatTestTableGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ class FormatTestTableGen : public ::testing::Test {
static void verifyFormat(llvm::StringRef Result, llvm::StringRef MessedUp) {
EXPECT_EQ(Result, format(MessedUp));
}

static void verifyFormat(llvm::StringRef Code, const FormatStyle &Style) {
EXPECT_EQ(Code.str(), format(Code, 0, Code.size(), Style))
<< "Expected code is not stable";
auto MessUp = test::messUp(Code);
EXPECT_EQ(Code.str(), format(MessUp, 0, MessUp.size(), Style));
}
};

TEST_F(FormatTestTableGen, FormatStringBreak) {
Expand Down Expand Up @@ -325,5 +332,19 @@ TEST_F(FormatTestTableGen, Assert) {
verifyFormat("assert !le(DefVar1, 0), \"Assert1\";\n");
}

TEST_F(FormatTestTableGen, CondOperatorAlignment) {
FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen);
Style.ColumnLimit = 60;
verifyFormat("let CondOpe1 = !cond(!eq(size, 1): 1,\n"
" !eq(size, 16): 1,\n"
" true: 0);\n",
Style);
Style.AlignConsecutiveTableGenCondOperatorColons.Enabled = true;
verifyFormat("let CondOpe1 = !cond(!eq(size, 1) : 1,\n"
" !eq(size, 16): 1,\n"
" true : 0);\n",
Style);
}

} // namespace format
} // end namespace clang
19 changes: 15 additions & 4 deletions clang/unittests/Serialization/ModuleCacheTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ class ModuleCacheTest : public ::testing::Test {
}
)cpp");
}

std::unique_ptr<CompilerInvocation>
createInvocationAndEnableFree(ArrayRef<const char *> Args,
CreateInvocationOptions Opts) {
std::unique_ptr<CompilerInvocation> Invocation =
createInvocation(Args, Opts);
if (Invocation)
Invocation->getFrontendOpts().DisableFree = false;

return Invocation;
}
};

TEST_F(ModuleCacheTest, CachedModuleNewPath) {
Expand All @@ -106,7 +117,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPath) {
MCPArg.c_str(), "-working-directory", TestDir.c_str(),
"test.m"};
std::shared_ptr<CompilerInvocation> Invocation =
createInvocation(Args, CIOpts);
createInvocationAndEnableFree(Args, CIOpts);
ASSERT_TRUE(Invocation);
CompilerInstance Instance;
Instance.setDiagnostics(Diags.get());
Expand All @@ -129,7 +140,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPath) {
"-Fframeworks", MCPArg.c_str(), "-working-directory",
TestDir.c_str(), "test.m"};
std::shared_ptr<CompilerInvocation> Invocation2 =
createInvocation(Args2, CIOpts);
createInvocationAndEnableFree(Args2, CIOpts);
ASSERT_TRUE(Invocation2);
CompilerInstance Instance2(Instance.getPCHContainerOperations(),
&Instance.getModuleCache());
Expand All @@ -156,7 +167,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPathAllowErrors) {
MCPArg.c_str(), "-working-directory", TestDir.c_str(),
"test.m"};
std::shared_ptr<CompilerInvocation> Invocation =
createInvocation(Args, CIOpts);
createInvocationAndEnableFree(Args, CIOpts);
ASSERT_TRUE(Invocation);
CompilerInstance Instance;
Instance.setDiagnostics(Diags.get());
Expand All @@ -173,7 +184,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPathAllowErrors) {
TestDir.c_str(), "-Xclang", "-fallow-pcm-with-compiler-errors",
"test.m"};
std::shared_ptr<CompilerInvocation> Invocation2 =
createInvocation(Args2, CIOpts);
createInvocationAndEnableFree(Args2, CIOpts);
ASSERT_TRUE(Invocation2);
CompilerInstance Instance2(Instance.getPCHContainerOperations(),
&Instance.getModuleCache());
Expand Down
1 change: 1 addition & 0 deletions clang/unittests/Serialization/VarDeclConstantInitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export namespace Fibonacci
std::shared_ptr<CompilerInvocation> Invocation =
createInvocation(Args, CIOpts);
ASSERT_TRUE(Invocation);
Invocation->getFrontendOpts().DisableFree = false;

CompilerInstance Instance;
Instance.setDiagnostics(Diags.get());
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/include/profile/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Value, \
INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Count, \
ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::PointerType::getUnqual(Ctx), Next, \
ConstantInt::get(llvm::Type::GetInt8PtrTy(Ctx), 0))
ConstantInt::get(llvm::PointerType::getUnqual(Ctx), 0))
#undef INSTR_PROF_VALUE_NODE
/* INSTR_PROF_VALUE_NODE end. */

Expand Down
14 changes: 0 additions & 14 deletions compiler-rt/lib/sanitizer_common/sanitizer_getauxval.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,6 @@ static inline decltype(AuxInfo::a_v) getauxval(decltype(AuxInfo::a_type) type) {
return 0;
}

#elif SANITIZER_FREEBSD
# include <sys/auxv.h>

# define SANITIZER_USE_GETAUXVAL 1
# define AT_EXECFN AT_EXECPATH

static inline unsigned long getauxval(unsigned long type) {
unsigned long buf = 0ul;

if (elf_aux_info(static_cast<int>(type), &buf, sizeof(buf)))
return 0ul;
return buf;
}

#endif

#endif // SANITIZER_GETAUXVAL_H
9 changes: 8 additions & 1 deletion compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -934,7 +934,14 @@ u64 MonotonicNanoTime() {
void ReExec() {
const char *pathname = "/proc/self/exe";

# if SANITIZER_NETBSD
# if SANITIZER_FREEBSD
for (const auto *aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
if (aux->a_type == AT_EXECPATH) {
pathname = static_cast<const char *>(aux->a_un.a_ptr);
break;
}
}
# elif SANITIZER_NETBSD
static const int name[] = {
CTL_KERN,
KERN_PROC_ARGS,
Expand Down
7 changes: 6 additions & 1 deletion flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,12 @@ void CheckHelper::CheckObjectEntity(
auto attr{*details.cudaDataAttr()};
switch (attr) {
case common::CUDADataAttr::Constant:
if (IsAllocatableOrPointer(symbol) || symbol.attrs().test(Attr::TARGET)) {
if (subpDetails && !inDeviceSubprogram) {
messages_.Say(
"Object '%s' with ATTRIBUTES(CONSTANT) may not be declared in a host subprogram"_err_en_US,
symbol.name());
} else if (IsAllocatableOrPointer(symbol) ||
symbol.attrs().test(Attr::TARGET)) {
messages_.Say(
"Object '%s' with ATTRIBUTES(CONSTANT) may not be allocatable, pointer, or target"_err_en_US,
symbol.name());
Expand Down
5 changes: 3 additions & 2 deletions flang/lib/Semantics/definable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,10 @@ static std::optional<parser::Message> WhyNotDefinableBase(parser::CharBlock at,
"'%s' is a host-associated allocatable and is not definable in a device subprogram"_err_en_US,
original);
} else if (*cudaDataAttr != common::CUDADataAttr::Device &&
*cudaDataAttr != common::CUDADataAttr::Managed) {
*cudaDataAttr != common::CUDADataAttr::Managed &&
*cudaDataAttr != common::CUDADataAttr::Shared) {
return BlameSymbol(at,
"'%s' is not device or managed data and is not definable in a device subprogram"_err_en_US,
"'%s' is not device or managed or shared data and is not definable in a device subprogram"_err_en_US,
original);
}
} else if (!isOwnedByDeviceCode) {
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6061,7 +6061,7 @@ void DeclarationVisitor::FinishNamelists() {
if (!symbol) {
symbol = &MakeSymbol(name, ObjectEntityDetails{});
ApplyImplicitRules(*symbol);
} else if (!ConvertToObjectEntity(*symbol)) {
} else if (!ConvertToObjectEntity(symbol->GetUltimate())) {
SayWithDecl(name, *symbol, "'%s' is not a variable"_err_en_US);
context().SetError(*groupSymbol);
}
Expand Down
10 changes: 0 additions & 10 deletions flang/test/Lower/CUDA/cuda-data-attribute.cuf
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,20 @@ module cuda_var
contains

subroutine local_var_attrs
real, constant :: rc
real, device :: rd
real, allocatable, managed :: rm
real, allocatable, pinned :: rp
end subroutine

! CHECK-LABEL: func.func @_QMcuda_varPlocal_var_attrs()
! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<constant>, uniq_name = "_QMcuda_varFlocal_var_attrsErc"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<device>, uniq_name = "_QMcuda_varFlocal_var_attrsErd"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFlocal_var_attrsErm"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<pinned>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFlocal_var_attrsErp"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)

! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda<constant>, uniq_name = "_QMcuda_varFlocal_var_attrsErc"} : (!fir.ref<f32>) -> !fir.ref<f32>
! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda<device>, uniq_name = "_QMcuda_varFlocal_var_attrsErd"} : (!fir.ref<f32>) -> !fir.ref<f32>
! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFlocal_var_attrsErm"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> !fir.ref<!fir.box<!fir.heap<f32>>>
! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda<pinned>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFlocal_var_attrsErp"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> !fir.ref<!fir.box<!fir.heap<f32>>>

subroutine dummy_arg_constant(dc)
real, constant :: dc
end subroutine
! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_constant(
! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<f32> {fir.bindc_name = "dc", fir.cuda_attr = #fir.cuda<constant>}
! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda<constant>, uniq_name = "_QMcuda_varFdummy_arg_constantEdc"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)

subroutine dummy_arg_device(dd)
real, device :: dd
end subroutine
Expand Down
13 changes: 13 additions & 0 deletions flang/test/Semantics/cuf03.cuf
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,18 @@ module m
real, managed :: ma(n) ! ok
!WARNING: Pointer 'dp' may not be associated in a device subprogram
real, device, pointer :: dp
real, constant :: rc ! ok
end subroutine

subroutine host()
!ERROR: Object 'rc' with ATTRIBUTES(CONSTANT) may not be declared in a host subprogram
real, constant :: rc
end subroutine

attributes(global) subroutine devsubr2()
real, shared :: rs

rs = 1 ! ok
end subroutine

end module
1 change: 1 addition & 0 deletions flang/test/Semantics/namelist01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ subroutine C8103a(x)
integer :: x
!ERROR: 'dupname' is already declared in this scoping unit
namelist /dupName/ x, x
namelist /nl/ uniquename ! ok
end subroutine C8103a

subroutine C8103b(y)
Expand Down
2 changes: 1 addition & 1 deletion flang/tools/bbc/bbc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,6 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
semanticsContext.targetCharacteristics(), parsing.allCooked(),
targetTriple, kindMap, loweringOptions, envDefaults,
semanticsContext.languageFeatures(), targetMachine);
burnside.lower(parseTree, semanticsContext);
mlir::ModuleOp mlirModule = burnside.getModule();
if (enableOpenMP) {
if (enableOpenMPGPU && !enableOpenMPDevice) {
Expand All @@ -376,6 +375,7 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
setOffloadModuleInterfaceAttributes(mlirModule, offloadModuleOpts);
setOpenMPVersionAttribute(mlirModule, setOpenMPVersion);
}
burnside.lower(parseTree, semanticsContext);
std::error_code ec;
std::string outputName = outputFilename;
if (!outputName.size())
Expand Down
8 changes: 4 additions & 4 deletions libc/AOR_v20.02/string/arm/memchr.S
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ __memchr_arm:
and r1,r1,#0xff @ Don't think we can trust the caller to actually pass a char

cmp r2,#16 @ If it's short don't bother with anything clever
blt 20f
blt 20f

tst r0, #7 @ If it's already aligned skip the next bit
beq 10f
Expand All @@ -62,7 +62,7 @@ __memchr_arm:
beq 50f @ If it matches exit found
tst r0, #7
bne 5b @ If not aligned yet then do next byte

10:
@ At this point, we are aligned, we know we have at least 8 bytes to work with
push {r4,r5,r6,r7}
Expand All @@ -71,7 +71,7 @@ __memchr_arm:
bic r4, r2, #7 @ Number of double words to work with
mvns r7, #0 @ all F's
movs r3, #0

15:
ldmia r0!,{r5,r6}
subs r4, r4, #8
Expand All @@ -87,7 +87,7 @@ __memchr_arm:
pop {r4,r5,r6,r7}
and r1,r1,#0xff @ Get r1 back to a single character from the expansion above
and r2,r2,#7 @ Leave the count remaining as the number after the double words have been done

20:
cbz r2, 40f @ 0 length or hit the end already then not found

Expand Down
2 changes: 1 addition & 1 deletion libc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ elseif(LIBC_CMAKE_VERBOSE_LOGGING)
message(STATUS "Path for config files is: ${LIBC_CONFIG_PATH}")
endif()

# option(LIBC_ENABLE_WIDE_CHARACTERS
# option(LIBC_ENABLE_WIDE_CHARACTERS
# "Whether to enable wide character functions on supported platforms. This may
# also set flags to enable or disable wide character support within other
# functions (e.g. printf)." ON)
Expand Down
4 changes: 2 additions & 2 deletions libc/benchmarks/automemcpy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ git clone https://github.com/Z3Prover/z3.git
python scripts/mk_make.py --prefix=<Z3_INSTALL_DIR>
cd build
make -j
make install
make install
```

## Configuration
Expand Down Expand Up @@ -68,7 +68,7 @@ Make sure to save the results of the benchmark as a json file.
By default, each function is benchmarked for at least one second, here we lower it to 200ms.

- `--benchmark_filter="BM_Memset|BM_Bzero"`

By default, all functions are benchmarked, here we restrict them to `memset` and `bzero`.

Other options might be useful, use `--help` for more information.
Expand Down
2 changes: 1 addition & 1 deletion libc/cmake/modules/CheckCompilerFeatures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
if(${feature} STREQUAL "float128")
set(LIBC_COMPILER_HAS_FLOAT128 TRUE)
elseif(${feature} STREQUAL "fixed_point")
set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
endif()
endif()
endforeach()
Expand Down
2 changes: 1 addition & 1 deletion libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function(_get_compile_options_from_flags output_var)
endif()
check_flag(ADD_SSE4_2_FLAG ${ROUND_OPT_FLAG} ${flags})
check_flag(ADD_EXPLICIT_SIMD_OPT_FLAG ${EXPLICIT_SIMD_OPT_FLAG} ${flags})

if(LLVM_COMPILER_IS_GCC_COMPATIBLE)
if(ADD_FMA_FLAG)
if(LIBC_TARGET_ARCHITECTURE_IS_X86)
Expand Down
Loading