42 changes: 12 additions & 30 deletions clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ enum IMAKind {
/// The reference is a contextually-permitted abstract member reference.
IMA_Abstract,

/// Whether the context is static is dependent on the enclosing template (i.e.
/// in a dependent class scope explicit specialization).
IMA_Dependent,

/// The reference may be to an unresolved using declaration and the
/// context is not an instance method.
IMA_Unresolved_StaticOrExplicitContext,
Expand Down Expand Up @@ -95,18 +91,10 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,

DeclContext *DC = SemaRef.getFunctionLevelDeclContext();

bool couldInstantiateToStatic = false;
bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull();

if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) {
if (MD->isImplicitObjectMemberFunction()) {
isStaticOrExplicitContext = false;
// A dependent class scope function template explicit specialization
// that is neither declared 'static' nor with an explicit object
// parameter could instantiate to a static or non-static member function.
couldInstantiateToStatic = MD->getDependentSpecializationInfo();
}
}
bool isStaticOrExplicitContext =
SemaRef.CXXThisTypeOverride.isNull() &&
(!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic() ||
cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction());

if (R.isUnresolvableResult())
return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext
Expand Down Expand Up @@ -135,9 +123,6 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
if (Classes.empty())
return IMA_Static;

if (couldInstantiateToStatic)
return IMA_Dependent;

// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
Expand Down Expand Up @@ -283,30 +268,27 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr(
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
UnresolvedLookupExpr *AsULE) {
switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {
switch (ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);

case IMA_Mixed:
case IMA_Mixed_Unrelated:
case IMA_Unresolved:
return BuildImplicitMemberExpr(
SS, TemplateKWLoc, R, TemplateArgs,
/*IsKnownInstance=*/Classification == IMA_Instance, S);
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
S);

case IMA_Field_Uneval_Context:
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
<< R.getLookupNameInfo().getName();
[[fallthrough]];
case IMA_Static:
case IMA_Abstract:
case IMA_Dependent:
case IMA_Mixed_StaticOrExplicitContext:
case IMA_Unresolved_StaticOrExplicitContext:
if (TemplateArgs || TemplateKWLoc.isValid())
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,
TemplateArgs);
return AsULE ? AsULE
: BuildDeclarationNameExpr(
SS, R, /*NeedsADL=*/false, /*AcceptInvalidDecl=*/false,
/*NeedUnresolved=*/Classification == IMA_Dependent);
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);

case IMA_Error_StaticOrExplicitContext:
case IMA_Error_Unrelated:
Expand Down
65 changes: 58 additions & 7 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,27 @@ bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,

bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
OpenACCClauseKind ClauseKind) {
// FIXME: For each clause as we implement them, we can add the
// 'legalization' list here.

// Do nothing so we can go to the 'unimplemented' diagnostic instead.
return true;
switch (ClauseKind) {
// FIXME: For each clause as we implement them, we can add the
// 'legalization' list here.
case OpenACCClauseKind::Default:
switch (DirectiveKind) {
case OpenACCDirectiveKind::Parallel:
case OpenACCDirectiveKind::Serial:
case OpenACCDirectiveKind::Kernels:
case OpenACCDirectiveKind::ParallelLoop:
case OpenACCDirectiveKind::SerialLoop:
case OpenACCDirectiveKind::KernelsLoop:
case OpenACCDirectiveKind::Data:
return true;
default:
return false;
}
default:
// Do nothing so we can go to the 'unimplemented' diagnostic instead.
return true;
}
llvm_unreachable("Invalid clause kind");
}
} // namespace

Expand All @@ -63,8 +79,43 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
return nullptr;
}

// TODO OpenACC: Switch over the clauses we implement here and 'create'
// them.
switch (Clause.getClauseKind()) {
case OpenACCClauseKind::Default: {
// Restrictions only properly implemented on 'compute' constructs, and
// 'compute' constructs are the only construct that can do anything with
// this yet, so skip/treat as unimplemented in this case.
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Parallel &&
Clause.getDirectiveKind() != OpenACCDirectiveKind::Serial &&
Clause.getDirectiveKind() != OpenACCDirectiveKind::Kernels)
break;

// Don't add an invalid clause to the AST.
if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
return nullptr;

// OpenACC 3.3, Section 2.5.4:
// At most one 'default' clause may appear, and it must have a value of
// either 'none' or 'present'.
// Second half of the sentence is diagnosed during parsing.
auto Itr = llvm::find_if(ExistingClauses, [](const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Default;
});

if (Itr != ExistingClauses.end()) {
SemaRef.Diag(Clause.getBeginLoc(),
diag::err_acc_duplicate_clause_disallowed)
<< Clause.getDirectiveKind() << Clause.getClauseKind();
SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
return nullptr;
}

return OpenACCDefaultClause::Create(
getASTContext(), Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
Clause.getLParenLoc(), Clause.getEndLoc());
}
default:
break;
}

Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
<< Clause.getClauseKind();
Expand Down
52 changes: 39 additions & 13 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// This implements Semantic Analysis for SYCL constructs.
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaSYCL.h"
#include "clang/AST/Mangle.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
Expand All @@ -18,28 +19,30 @@ using namespace clang;
// SYCL device specific diagnostics implementation
// -----------------------------------------------------------------------------

Sema::SemaDiagnosticBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
SemaSYCL::SemaSYCL(Sema &S) : SemaBase(S) {}

Sema::SemaDiagnosticBuilder SemaSYCL::DiagIfDeviceCode(SourceLocation Loc,
unsigned DiagID) {
assert(getLangOpts().SYCLIsDevice &&
"Should only be called during SYCL compilation");
FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.getCurLexicalContext());
SemaDiagnosticBuilder::Kind DiagKind = [this, FD] {
if (!FD)
return SemaDiagnosticBuilder::K_Nop;
if (getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted)
if (SemaRef.getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted)
return SemaDiagnosticBuilder::K_ImmediateWithCallStack;
return SemaDiagnosticBuilder::K_Deferred;
}();
return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, *this);
return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, SemaRef);
}

static bool isZeroSizedArray(Sema &SemaRef, QualType Ty) {
if (const auto *CAT = SemaRef.getASTContext().getAsConstantArrayType(Ty))
static bool isZeroSizedArray(SemaSYCL &S, QualType Ty) {
if (const auto *CAT = S.getASTContext().getAsConstantArrayType(Ty))
return CAT->isZeroSize();
return false;
}

void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
void SemaSYCL::deepTypeCheckForDevice(SourceLocation UsedAt,
llvm::DenseSet<QualType> Visited,
ValueDecl *DeclToCheck) {
assert(getLangOpts().SYCLIsDevice &&
Expand All @@ -51,18 +54,18 @@ void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
auto Check = [&](QualType TypeToCheck, const ValueDecl *D) {
bool ErrorFound = false;
if (isZeroSizedArray(*this, TypeToCheck)) {
SYCLDiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
DiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
ErrorFound = true;
}
// Checks for other types can also be done here.
if (ErrorFound) {
if (NeedToEmitNotes) {
if (auto *FD = dyn_cast<FieldDecl>(D))
SYCLDiagIfDeviceCode(FD->getLocation(),
diag::note_illegal_field_declared_here)
DiagIfDeviceCode(FD->getLocation(),
diag::note_illegal_field_declared_here)
<< FD->getType()->isPointerType() << FD->getType();
else
SYCLDiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
DiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
}
}

Expand Down Expand Up @@ -93,8 +96,8 @@ void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
auto EmitHistory = [&]() {
// The first element is always nullptr.
for (uint64_t Index = 1; Index < History.size(); ++Index) {
SYCLDiagIfDeviceCode(History[Index]->getLocation(),
diag::note_within_field_of_type)
DiagIfDeviceCode(History[Index]->getLocation(),
diag::note_within_field_of_type)
<< History[Index]->getType();
}
};
Expand Down Expand Up @@ -130,3 +133,26 @@ void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
}
} while (!StackForRecursion.empty());
}

ExprResult SemaSYCL::BuildUniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
TypeSourceInfo *TSI) {
return SYCLUniqueStableNameExpr::Create(getASTContext(), OpLoc, LParen,
RParen, TSI);
}

ExprResult SemaSYCL::ActOnUniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
ParsedType ParsedTy) {
TypeSourceInfo *TSI = nullptr;
QualType Ty = SemaRef.GetTypeFromParser(ParsedTy, &TSI);

if (Ty.isNull())
return ExprError();
if (!TSI)
TSI = getASTContext().getTrivialTypeSourceInfo(Ty, LParen);

return BuildUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
}
8 changes: 0 additions & 8 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5093,14 +5093,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
EnterExpressionEvaluationContext EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);

Qualifiers ThisTypeQuals;
CXXRecordDecl *ThisContext = nullptr;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
ThisContext = Method->getParent();
ThisTypeQuals = Method->getMethodQualifiers();
}
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals);

// Introduce a new scope where local variable instantiations will be
// recorded, unless we're actually a member function within a local
// class, in which case we need to merge our results with the parent
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,17 @@ std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
// expanded this pack expansion into the enclosing pack if we could.
if (Elem.isPackExpansion())
return std::nullopt;
// Don't guess the size of unexpanded packs. The pack within a template
// argument may have yet to be of a PackExpansion type before we see the
// ellipsis in the annotation stage.
//
// This doesn't mean we would invalidate the optimization: Arg can be an
// unexpanded pack regardless of Elem's dependence. For instance,
// A TemplateArgument that contains either a SubstTemplateTypeParmPackType
// or SubstNonTypeTemplateParmPackExpr is always considered Unexpanded, but
// the underlying TemplateArgument thereof may not.
if (Elem.containsUnexpandedParameterPack())
return std::nullopt;
}
return Pack.pack_size();
}
Expand Down
53 changes: 45 additions & 8 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaOpenACC.h"
#include "clang/Sema/SemaSYCL.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
Expand Down Expand Up @@ -2632,7 +2633,8 @@ class TreeTransform {
SourceLocation LParen,
SourceLocation RParen,
TypeSourceInfo *TSI) {
return getSema().BuildSYCLUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
return getSema().SYCL().BuildUniqueStableNameExpr(OpLoc, LParen, RParen,
TSI);
}

/// Build a new predefined expression.
Expand Down Expand Up @@ -3307,13 +3309,12 @@ class TreeTransform {

/// Build a new C++ "this" expression.
///
/// By default, performs semantic analysis to build a new "this" expression.
/// Subclasses may override this routine to provide different behavior.
/// By default, builds a new "this" expression without performing any
/// semantic analysis. Subclasses may override this routine to provide
/// different behavior.
ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
QualType ThisType,
bool isImplicit) {
if (getSema().CheckCXXThisType(ThisLoc, ThisType))
return ExprError();
return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit);
}

Expand Down Expand Up @@ -4034,6 +4035,11 @@ class TreeTransform {
llvm::SmallVector<OpenACCClause *>
TransformOpenACCClauseList(OpenACCDirectiveKind DirKind,
ArrayRef<const OpenACCClause *> OldClauses);

OpenACCClause *
TransformOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirKind,
const OpenACCClause *OldClause);
};

template <typename Derived>
Expand Down Expand Up @@ -11074,13 +11080,44 @@ OMPClause *TreeTransform<Derived>::TransformOMPXBareClause(OMPXBareClause *C) {
//===----------------------------------------------------------------------===//
// OpenACC transformation
//===----------------------------------------------------------------------===//
template <typename Derived>
OpenACCClause *TreeTransform<Derived>::TransformOpenACCClause(
ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirKind, const OpenACCClause *OldClause) {

SemaOpenACC::OpenACCParsedClause ParsedClause(
DirKind, OldClause->getClauseKind(), OldClause->getBeginLoc());
ParsedClause.setEndLoc(OldClause->getEndLoc());

if (const auto *WithParms = dyn_cast<OpenACCClauseWithParams>(OldClause))
ParsedClause.setLParenLoc(WithParms->getLParenLoc());

switch (OldClause->getClauseKind()) {
case OpenACCClauseKind::Default:
// There is nothing to do here as nothing dependent can appear in this
// clause. So just set the values so Sema can set the right value.
ParsedClause.setDefaultDetails(
cast<OpenACCDefaultClause>(OldClause)->getDefaultClauseKind());
break;
default:
assert(false && "Unhandled OpenACC clause in TreeTransform");
return nullptr;
}

return getSema().OpenACC().ActOnClause(ExistingClauses, ParsedClause);
}

template <typename Derived>
llvm::SmallVector<OpenACCClause *>
TreeTransform<Derived>::TransformOpenACCClauseList(
OpenACCDirectiveKind DirKind, ArrayRef<const OpenACCClause *> OldClauses) {
// TODO OpenACC: Ensure we loop through the list and transform the individual
// clauses.
return {};
llvm::SmallVector<OpenACCClause *> TransformedClauses;
for (const auto *Clause : OldClauses) {
if (OpenACCClause *TransformedClause = getDerived().TransformOpenACCClause(
TransformedClauses, DirKind, Clause))
TransformedClauses.push_back(TransformedClause);
}
return TransformedClauses;
}

template <typename Derived>
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11763,7 +11763,12 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
[[maybe_unused]] SourceLocation EndLoc = readSourceLocation();

switch (ClauseKind) {
case OpenACCClauseKind::Default:
case OpenACCClauseKind::Default: {
SourceLocation LParenLoc = readSourceLocation();
OpenACCDefaultClauseKind DCK = readEnum<OpenACCDefaultClauseKind>();
return OpenACCDefaultClause::Create(getContext(), DCK, BeginLoc, LParenLoc,
EndLoc);
}
case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
case OpenACCClauseKind::Seq:
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7406,7 +7406,12 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
writeSourceLocation(C->getEndLoc());

switch (C->getClauseKind()) {
case OpenACCClauseKind::Default:
case OpenACCClauseKind::Default: {
const auto *DC = cast<OpenACCDefaultClause>(C);
writeSourceLocation(DC->getLParenLoc());
writeEnum(DC->getDefaultClauseKind());
return;
}
case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
case OpenACCClauseKind::Seq:
Expand Down
33 changes: 13 additions & 20 deletions clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,22 +363,17 @@ class DependencyScanningAction : public tooling::ToolAction {
PrebuiltModuleVFSMap, ScanInstance.getDiagnostics()))
return false;

auto AdjustCI = [&](CompilerInstance &CI) {
// Set up the dependency scanning file system callback if requested.
if (DepFS) {
auto GetDependencyDirectives = [LocalDepFS = DepFS](FileEntryRef File)
-> std::optional<ArrayRef<dependency_directives_scan::Directive>> {
if (llvm::ErrorOr<EntryRef> Entry =
LocalDepFS->getOrCreateFileSystemEntry(File.getName()))
if (LocalDepFS->ensureDirectiveTokensArePopulated(*Entry))
return Entry->getDirectiveTokens();
return std::nullopt;
};

CI.getPreprocessor().setDependencyDirectivesFn(
std::move(GetDependencyDirectives));
}
};
// Use the dependency scanning optimized file system if requested to do so.
if (DepFS)
ScanInstance.getPreprocessorOpts().DependencyDirectivesForFile =
[LocalDepFS = DepFS](FileEntryRef File)
-> std::optional<ArrayRef<dependency_directives_scan::Directive>> {
if (llvm::ErrorOr<EntryRef> Entry =
LocalDepFS->getOrCreateFileSystemEntry(File.getName()))
if (LocalDepFS->ensureDirectiveTokensArePopulated(*Entry))
return Entry->getDirectiveTokens();
return std::nullopt;
};

// Create the dependency collector that will collect the produced
// dependencies.
Expand Down Expand Up @@ -430,11 +425,9 @@ class DependencyScanningAction : public tooling::ToolAction {
std::unique_ptr<FrontendAction> Action;

if (ModuleName)
Action = std::make_unique<GetDependenciesByModuleNameAction>(
*ModuleName, std::move(AdjustCI));
Action = std::make_unique<GetDependenciesByModuleNameAction>(*ModuleName);
else
Action =
std::make_unique<ReadPCHAndPreprocessAction>(std::move(AdjustCI));
Action = std::make_unique<ReadPCHAndPreprocessAction>();

if (ScanInstance.getDiagnostics().hasErrorOccurred())
return false;
Expand Down
1 change: 1 addition & 0 deletions clang/test/APINotes/instancetype.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -verify %s

@import InstancetypeModule;
Expand Down
120 changes: 120 additions & 0 deletions clang/test/AST/Interp/builtin-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,9 @@ void test_noexcept(int *i) {
#undef TEST_TYPE
} // end namespace test_launder


/// FIXME: The commented out tests here use a IntAP value and fail.
/// This currently means we will leak the IntAP value since nothing cleans it up.
namespace clz {
char clz1[__builtin_clz(1) == BITSIZE(int) - 1 ? 1 : -1];
char clz2[__builtin_clz(7) == BITSIZE(int) - 3 ? 1 : -1];
Expand All @@ -492,6 +495,63 @@ namespace clz {
char clz7[__builtin_clzs(0x1) == BITSIZE(short) - 1 ? 1 : -1];
char clz8[__builtin_clzs(0xf) == BITSIZE(short) - 4 ? 1 : -1];
char clz9[__builtin_clzs(0xfff) == BITSIZE(short) - 12 ? 1 : -1];

int clz10 = __builtin_clzg((unsigned char)0);
char clz11[__builtin_clzg((unsigned char)0, 42) == 42 ? 1 : -1];
char clz12[__builtin_clzg((unsigned char)0x1) == BITSIZE(char) - 1 ? 1 : -1];
char clz13[__builtin_clzg((unsigned char)0x1, 42) == BITSIZE(char) - 1 ? 1 : -1];
char clz14[__builtin_clzg((unsigned char)0xf) == BITSIZE(char) - 4 ? 1 : -1];
char clz15[__builtin_clzg((unsigned char)0xf, 42) == BITSIZE(char) - 4 ? 1 : -1];
char clz16[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1))) == 0 ? 1 : -1];
char clz17[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == 0 ? 1 : -1];
int clz18 = __builtin_clzg((unsigned short)0);
char clz19[__builtin_clzg((unsigned short)0, 42) == 42 ? 1 : -1];
char clz20[__builtin_clzg((unsigned short)0x1) == BITSIZE(short) - 1 ? 1 : -1];
char clz21[__builtin_clzg((unsigned short)0x1, 42) == BITSIZE(short) - 1 ? 1 : -1];
char clz22[__builtin_clzg((unsigned short)0xf) == BITSIZE(short) - 4 ? 1 : -1];
char clz23[__builtin_clzg((unsigned short)0xf, 42) == BITSIZE(short) - 4 ? 1 : -1];
char clz24[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1))) == 0 ? 1 : -1];
char clz25[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == 0 ? 1 : -1];
int clz26 = __builtin_clzg(0U);
char clz27[__builtin_clzg(0U, 42) == 42 ? 1 : -1];
char clz28[__builtin_clzg(0x1U) == BITSIZE(int) - 1 ? 1 : -1];
char clz29[__builtin_clzg(0x1U, 42) == BITSIZE(int) - 1 ? 1 : -1];
char clz30[__builtin_clzg(0xfU) == BITSIZE(int) - 4 ? 1 : -1];
char clz31[__builtin_clzg(0xfU, 42) == BITSIZE(int) - 4 ? 1 : -1];
char clz32[__builtin_clzg(1U << (BITSIZE(int) - 1)) == 0 ? 1 : -1];
char clz33[__builtin_clzg(1U << (BITSIZE(int) - 1), 42) == 0 ? 1 : -1];
int clz34 = __builtin_clzg(0UL);
char clz35[__builtin_clzg(0UL, 42) == 42 ? 1 : -1];
char clz36[__builtin_clzg(0x1UL) == BITSIZE(long) - 1 ? 1 : -1];
char clz37[__builtin_clzg(0x1UL, 42) == BITSIZE(long) - 1 ? 1 : -1];
char clz38[__builtin_clzg(0xfUL) == BITSIZE(long) - 4 ? 1 : -1];
char clz39[__builtin_clzg(0xfUL, 42) == BITSIZE(long) - 4 ? 1 : -1];
char clz40[__builtin_clzg(1UL << (BITSIZE(long) - 1)) == 0 ? 1 : -1];
char clz41[__builtin_clzg(1UL << (BITSIZE(long) - 1), 42) == 0 ? 1 : -1];
int clz42 = __builtin_clzg(0ULL);
char clz43[__builtin_clzg(0ULL, 42) == 42 ? 1 : -1];
char clz44[__builtin_clzg(0x1ULL) == BITSIZE(long long) - 1 ? 1 : -1];
char clz45[__builtin_clzg(0x1ULL, 42) == BITSIZE(long long) - 1 ? 1 : -1];
char clz46[__builtin_clzg(0xfULL) == BITSIZE(long long) - 4 ? 1 : -1];
char clz47[__builtin_clzg(0xfULL, 42) == BITSIZE(long long) - 4 ? 1 : -1];
char clz48[__builtin_clzg(1ULL << (BITSIZE(long long) - 1)) == 0 ? 1 : -1];
char clz49[__builtin_clzg(1ULL << (BITSIZE(long long) - 1), 42) == 0 ? 1 : -1];
#ifdef __SIZEOF_INT128__
// int clz50 = __builtin_clzg((unsigned __int128)0);
char clz51[__builtin_clzg((unsigned __int128)0, 42) == 42 ? 1 : -1];
char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 : -1];
char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1];
char clz54[__builtin_clzg((unsigned __int128)0xf) == BITSIZE(__int128) - 4 ? 1 : -1];
char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1];
#endif
#ifndef __AVR__
// int clz58 = __builtin_clzg((unsigned _BitInt(128))0);
char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char clz62[__builtin_clzg((unsigned _BitInt(128))0xf) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
char clz63[__builtin_clzg((unsigned _BitInt(128))0xf, 42) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
#endif
}

namespace ctz {
Expand All @@ -502,6 +562,66 @@ namespace ctz {
char ctz5[__builtin_ctzl(0x10L) == 4 ? 1 : -1];
char ctz6[__builtin_ctzll(0x100LL) == 8 ? 1 : -1];
char ctz7[__builtin_ctzs(1 << (BITSIZE(short) - 1)) == BITSIZE(short) - 1 ? 1 : -1];
int ctz8 = __builtin_ctzg((unsigned char)0);
char ctz9[__builtin_ctzg((unsigned char)0, 42) == 42 ? 1 : -1];
char ctz10[__builtin_ctzg((unsigned char)0x1) == 0 ? 1 : -1];
char ctz11[__builtin_ctzg((unsigned char)0x1, 42) == 0 ? 1 : -1];
char ctz12[__builtin_ctzg((unsigned char)0x10) == 4 ? 1 : -1];
char ctz13[__builtin_ctzg((unsigned char)0x10, 42) == 4 ? 1 : -1];
char ctz14[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1))) == BITSIZE(char) - 1 ? 1 : -1];
char ctz15[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == BITSIZE(char) - 1 ? 1 : -1];
int ctz16 = __builtin_ctzg((unsigned short)0);
char ctz17[__builtin_ctzg((unsigned short)0, 42) == 42 ? 1 : -1];
char ctz18[__builtin_ctzg((unsigned short)0x1) == 0 ? 1 : -1];
char ctz19[__builtin_ctzg((unsigned short)0x1, 42) == 0 ? 1 : -1];
char ctz20[__builtin_ctzg((unsigned short)0x10) == 4 ? 1 : -1];
char ctz21[__builtin_ctzg((unsigned short)0x10, 42) == 4 ? 1 : -1];
char ctz22[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1))) == BITSIZE(short) - 1 ? 1 : -1];
char ctz23[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == BITSIZE(short) - 1 ? 1 : -1];
int ctz24 = __builtin_ctzg(0U);
char ctz25[__builtin_ctzg(0U, 42) == 42 ? 1 : -1];
char ctz26[__builtin_ctzg(0x1U) == 0 ? 1 : -1];
char ctz27[__builtin_ctzg(0x1U, 42) == 0 ? 1 : -1];
char ctz28[__builtin_ctzg(0x10U) == 4 ? 1 : -1];
char ctz29[__builtin_ctzg(0x10U, 42) == 4 ? 1 : -1];
char ctz30[__builtin_ctzg(1U << (BITSIZE(int) - 1)) == BITSIZE(int) - 1 ? 1 : -1];
char ctz31[__builtin_ctzg(1U << (BITSIZE(int) - 1), 42) == BITSIZE(int) - 1 ? 1 : -1];
int ctz32 = __builtin_ctzg(0UL);
char ctz33[__builtin_ctzg(0UL, 42) == 42 ? 1 : -1];
char ctz34[__builtin_ctzg(0x1UL) == 0 ? 1 : -1];
char ctz35[__builtin_ctzg(0x1UL, 42) == 0 ? 1 : -1];
char ctz36[__builtin_ctzg(0x10UL) == 4 ? 1 : -1];
char ctz37[__builtin_ctzg(0x10UL, 42) == 4 ? 1 : -1];
char ctz38[__builtin_ctzg(1UL << (BITSIZE(long) - 1)) == BITSIZE(long) - 1 ? 1 : -1];
char ctz39[__builtin_ctzg(1UL << (BITSIZE(long) - 1), 42) == BITSIZE(long) - 1 ? 1 : -1];
int ctz40 = __builtin_ctzg(0ULL);
char ctz41[__builtin_ctzg(0ULL, 42) == 42 ? 1 : -1];
char ctz42[__builtin_ctzg(0x1ULL) == 0 ? 1 : -1];
char ctz43[__builtin_ctzg(0x1ULL, 42) == 0 ? 1 : -1];
char ctz44[__builtin_ctzg(0x10ULL) == 4 ? 1 : -1];
char ctz45[__builtin_ctzg(0x10ULL, 42) == 4 ? 1 : -1];
char ctz46[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1)) == BITSIZE(long long) - 1 ? 1 : -1];
char ctz47[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1), 42) == BITSIZE(long long) - 1 ? 1 : -1];
#ifdef __SIZEOF_INT128__
// int ctz48 = __builtin_ctzg((unsigned __int128)0);
char ctz49[__builtin_ctzg((unsigned __int128)0, 42) == 42 ? 1 : -1];
char ctz50[__builtin_ctzg((unsigned __int128)0x1) == 0 ? 1 : -1];
char ctz51[__builtin_ctzg((unsigned __int128)0x1, 42) == 0 ? 1 : -1];
char ctz52[__builtin_ctzg((unsigned __int128)0x10) == 4 ? 1 : -1];
char ctz53[__builtin_ctzg((unsigned __int128)0x10, 42) == 4 ? 1 : -1];
char ctz54[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1)) == BITSIZE(__int128) - 1 ? 1 : -1];
char ctz55[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1), 42) == BITSIZE(__int128) - 1 ? 1 : -1];
#endif
#ifndef __AVR__
// int ctz56 = __builtin_ctzg((unsigned _BitInt(128))0);
char ctz57[__builtin_ctzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
char ctz58[__builtin_ctzg((unsigned _BitInt(128))0x1) == 0 ? 1 : -1];
char ctz59[__builtin_ctzg((unsigned _BitInt(128))0x1, 42) == 0 ? 1 : -1];
char ctz60[__builtin_ctzg((unsigned _BitInt(128))0x10) == 4 ? 1 : -1];
char ctz61[__builtin_ctzg((unsigned _BitInt(128))0x10, 42) == 4 ? 1 : -1];
char ctz62[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1)) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char ctz63[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1), 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
#endif
}

namespace bswap {
Expand Down
18 changes: 18 additions & 0 deletions clang/test/AST/Interp/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,21 @@ const struct StrA * const sb = &sa;
const struct StrA sc = *sb;
_Static_assert(sc.a == 12, ""); // pedantic-ref-warning {{GNU extension}} \
// pedantic-expected-warning {{GNU extension}}

_Static_assert(((void*)0 + 1) != (void*)0, ""); // pedantic-expected-warning {{arithmetic on a pointer to void is a GNU extension}} \
// pedantic-expected-warning {{not an integer constant expression}} \
// pedantic-expected-note {{cannot perform pointer arithmetic on null pointer}} \
// pedantic-ref-warning {{arithmetic on a pointer to void is a GNU extension}} \
// pedantic-ref-warning {{not an integer constant expression}} \
// pedantic-ref-note {{cannot perform pointer arithmetic on null pointer}}

typedef __INTPTR_TYPE__ intptr_t;
int array[(intptr_t)(int*)1]; // ref-warning {{variable length array folded to constant array}} \
// pedantic-ref-warning {{variable length array folded to constant array}} \
// expected-warning {{variable length array folded to constant array}} \
// pedantic-expected-warning {{variable length array folded to constant array}}

int castViaInt[*(int*)(unsigned long)"test"]; // ref-error {{variable length array}} \
// pedantic-ref-error {{variable length array}} \
// expected-error {{variable length array}} \
// pedantic-expected-error {{variable length array}}
192 changes: 192 additions & 0 deletions clang/test/AST/Interp/const-eval.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// RUN: %clang_cc1 -fsyntax-only -verify=both,ref -triple x86_64-linux %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast
// RUN: %clang_cc1 -fsyntax-only -verify=both,expected -triple x86_64-linux %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast -fexperimental-new-constant-interpreter -DNEW_INTERP
// RUN: %clang_cc1 -fsyntax-only -verify=both,ref -triple powerpc64-ibm-aix-xcoff %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast
// RUN: %clang_cc1 -fsyntax-only -verify=both,expected -triple powerpc64-ibm-aix-xcoff %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast -fexperimental-new-constant-interpreter -DNEW_INTERP

/// This is a version of test/Sema/const-eval.c with the
/// tests commented out that the new constant expression interpreter does
/// not support yet. They are all marked with the NEW_INTERP define:
///
/// - builtin_constant_p
/// - unions


#define EVAL_EXPR(testno, expr) enum { test##testno = (expr) }; struct check_positive##testno { int a[test##testno]; };
int x;
EVAL_EXPR(1, (_Bool)&x)
EVAL_EXPR(2, (int)(1.0+(double)4))
EVAL_EXPR(3, (int)(1.0+(float)4.0))
EVAL_EXPR(4, (_Bool)(1 ? (void*)&x : 0))
EVAL_EXPR(5, (_Bool)(int[]){0})
struct y {int x,y;};
EVAL_EXPR(6, (int)(1+(struct y*)0))
_Static_assert((long)&((struct y*)0)->y > 0, "");
EVAL_EXPR(7, (int)&((struct y*)0)->y)
EVAL_EXPR(8, (_Bool)"asdf")
EVAL_EXPR(9, !!&x)
EVAL_EXPR(10, ((void)1, 12))
void g0(void);
EVAL_EXPR(11, (g0(), 12)) // both-error {{not an integer constant expression}}
EVAL_EXPR(12, 1.0&&2.0)
EVAL_EXPR(13, x || 3.0) // both-error {{not an integer constant expression}}

unsigned int l_19 = 1;
EVAL_EXPR(14, (1 ^ l_19) && 1); // both-error {{not an integer constant expression}}

void f(void)
{
int a;
EVAL_EXPR(15, (_Bool)&a);
}

_Complex float g16 = (1.0f + 1.0fi);

// ?: in constant expressions.
int g17[(3?:1) - 2];

EVAL_EXPR(18, ((int)((void*)10 + 10)) == 20 ? 1 : -1);

struct s {
int a[(int)-1.0f]; // both-error {{array size is negative}}
};

EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1));

#ifndef NEW_INTERP
EVAL_EXPR(20, __builtin_constant_p(*((int*) 10)));
#endif

EVAL_EXPR(21, (__imag__ 2i) == 2 ? 1 : -1);

EVAL_EXPR(22, (__real__ (2i+3)) == 3 ? 1 : -1);

int g23[(int)(1.0 / 1.0)] = { 1 }; // both-warning {{folded to constant array}}
int g24[(int)(1.0 / 1.0)] = { 1 , 2 }; // both-warning {{folded to constant array}} \
// both-warning {{excess elements in array initializer}}
int g25[(int)(1.0 + 1.0)], g26 = sizeof(g25); // both-warning {{folded to constant array}}

EVAL_EXPR(26, (_Complex double)0 ? -1 : 1)
EVAL_EXPR(27, (_Complex int)0 ? -1 : 1)
EVAL_EXPR(28, (_Complex double)1 ? 1 : -1)
EVAL_EXPR(29, (_Complex int)1 ? 1 : -1)

// PR4027
struct a { int x, y; };
static struct a V2 = (struct a)(struct a){ 1, 2};
static const struct a V1 = (struct a){ 1, 2};

EVAL_EXPR(30, (int)(_Complex float)((1<<30)-1) == (1<<30) ? 1 : -1)
EVAL_EXPR(31, (int*)0 == (int*)0 ? 1 : -1)
EVAL_EXPR(32, (int*)0 != (int*)0 ? -1 : 1)
EVAL_EXPR(33, (void*)0 - (void*)0 == 0 ? 1 : -1)

void foo(void) {}
EVAL_EXPR(34, (foo == (void *)0) ? -1 : 1)

// No PR. Mismatched bitwidths lead to a crash on second evaluation.
const _Bool constbool = 0;
EVAL_EXPR(35, constbool)
EVAL_EXPR(36, constbool)

EVAL_EXPR(37, ((void)1,2.0) == 2.0 ? 1 : -1)
EVAL_EXPR(38, __builtin_expect(1,1) == 1 ? 1 : -1)

// PR7884
EVAL_EXPR(39, __real__(1.f) == 1 ? 1 : -1)
EVAL_EXPR(40, __imag__(1.f) == 0 ? 1 : -1)

// From gcc testsuite
EVAL_EXPR(41, (int)(1+(_Complex unsigned)2))

void rdar8875946(void) {
double _Complex P;
float _Complex P2 = 3.3f + P;
}

double d = (d = 0.0); // both-error {{not a compile-time constant}}
double d2 = ++d; // both-error {{not a compile-time constant}}

int n = 2;
int intLvalue[*(int*)((long)&n ?: 1)] = { 1, 2 }; // both-error {{variable length array}}

union u { int a; char b[4]; };
char c = ((union u)(123456)).b[0]; // both-error {{not a compile-time constant}}

#ifndef NEW_INTERP
extern const int weak_int __attribute__((weak));
const int weak_int = 42;
int weak_int_test = weak_int; // both-error {{not a compile-time constant}}
#endif

int literalVsNull1 = "foo" == 0;
int literalVsNull2 = 0 == "foo";

// PR11385.
int castViaInt[*(int*)(unsigned long)"test"]; // both-error {{variable length array}}

// PR11391.
#ifndef NEW_INTERP
struct PR11391 { _Complex float f; } pr11391;
EVAL_EXPR(42, __builtin_constant_p(pr11391.f = 1))
#endif

// PR12043
float varfloat;
const float constfloat = 0;
EVAL_EXPR(43, varfloat && constfloat) // both-error {{not an integer constant expression}}
EVAL_EXPR(45, ((char*)-1) + 1 == 0 ? 1 : -1)
EVAL_EXPR(46, ((char*)-1) + 1 < (char*) -1 ? 1 : -1)
EVAL_EXPR(47, &x < &x + 1 ? 1 : -1)
EVAL_EXPR(48, &x != &x - 1 ? 1 : -1)
EVAL_EXPR(49, &x < &x - 100 ? 1 : -1) // ref-error {{not an integer constant expression}}

/// FIXME: Rejecting this is correct, BUT when converting the innermost pointer
/// to an integer, we do not preserve the information where it came from. So when we later
/// create a pointer from it, it also doesn't have that information, which means
/// hasSameBase() for those two pointers will return false. And in those cases, we emit
/// the diagnostic:
/// comparison between '&Test50' and '&(631578)' has unspecified value
extern struct Test50S Test50;
EVAL_EXPR(50, &Test50 < (struct Test50S*)((unsigned long)&Test50 + 10)) // both-error {{not an integer constant expression}} \
// expected-note {{comparison between}}

EVAL_EXPR(51, 0 != (float)1e99)

// PR21945
void PR21945(void) { int i = (({}), 0l); }

void PR24622(void);
struct PR24622 {} pr24622;
EVAL_EXPR(52, &pr24622 == (void *)&PR24622);

// We evaluate these by providing 2s' complement semantics in constant
// expressions, like we do for integers.
void *PR28739a = (__int128)(unsigned long)-1 + &PR28739a; // both-warning {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 64-bit (8-byte) elements (max possible 2305843009213693952 elements)}}

void *PR28739b = &PR28739b + (__int128)(unsigned long)-1; // both-warning {{refers past the last possible element}}
__int128 PR28739c = (&PR28739c + (__int128)(unsigned long)-1) - &PR28739c; // both-warning {{refers past the last possible element}}
void *PR28739d = &(&PR28739d)[(__int128)(unsigned long)-1]; // both-warning {{refers past the last possible element}}

struct PR35214_X {
int k;
int arr[];
};
int PR35214_x;
int PR35214_y = ((struct PR35214_X *)&PR35214_x)->arr[1]; // both-error {{not a compile-time constant}}
#ifndef NEW_INTERP
int *PR35214_z = &((struct PR35214_X *)&PR35214_x)->arr[1]; // ok, &PR35214_x + 2
#endif

/// From const-eval-64.c
EVAL_EXPR(53, ((char*)-1LL) + 1 == 0 ? 1 : -1)
EVAL_EXPR(54, ((char*)-1LL) + 1 < (char*) -1 ? 1 : -1)

/// === Additions ===
#if __SIZEOF_INT__ == 4
typedef __INTPTR_TYPE__ intptr_t;
const intptr_t A = (intptr_t)(((int*) 0) + 1);
const intptr_t B = (intptr_t)(((char*)0) + 3);
_Static_assert(A > B, "");
#else
#error :(
#endif
15 changes: 15 additions & 0 deletions clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,21 @@ namespace FunctionReturnType {
constexpr int (*invalidFnPtr)() = m;
static_assert(invalidFnPtr() == 5, ""); // both-error {{not an integral constant expression}} \
// both-note {{non-constexpr function 'm'}}


namespace ToBool {
void mismatched(int x) {}
typedef void (*callback_t)(int);
void foo() {
callback_t callback = (callback_t)mismatched; // warns
/// Casts a function pointer to a boolean and then back to a function pointer.
/// This is extracted from test/Sema/callingconv-cast.c
callback = (callback_t)!mismatched; // both-warning {{address of function 'mismatched' will always evaluate to 'true'}} \
// both-note {{prefix with the address-of operator to silence this warning}}
}
}


}

namespace Comparison {
Expand Down
22 changes: 22 additions & 0 deletions clang/test/AST/Interp/vectors.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -verify=ref,both %s

// both-no-diagnostics

typedef int __attribute__((vector_size(16))) VI4;
constexpr VI4 A = {1,2,3,4};

/// From constant-expression-cxx11.cpp
namespace Vector {
typedef int __attribute__((vector_size(16))) VI4;
constexpr VI4 f(int n) {
return VI4 { n * 3, n + 4, n - 5, n / 6 };
}
constexpr auto v1 = f(10);

typedef double __attribute__((vector_size(32))) VD4;
constexpr VD4 g(int n) {
return (VD4) { n / 2.0, n + 1.5, n - 5.4, n * 0.9 };
}
constexpr auto v2 = g(4);
}
14 changes: 14 additions & 0 deletions clang/test/C/C11/n1514.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %clang_cc1 -verify -std=c11 %s
// expected-no-diagnostics

/* WG14 N1514: Yes
* Conditional normative status for Annex G
*/

// We don't support Annex G (which introduces imaginary types), but support for
// this annex is conditional in C11. So we can test for conformance to this
// paper by ensuring we don't define the macro claiming we support Annex G.

#ifdef __STDC_IEC_559_COMPLEX__
#error "when did this happen??"
#endif
File renamed without changes.
24 changes: 24 additions & 0 deletions clang/test/ClangScanDeps/modules-minimize-module.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: rm -rf %t
// RUN: split-file %s %t

// This test checks that source files of modules undergo dependency directives
// scan. If a.h would not, the scan would fail when lexing `#error`.

//--- module.modulemap
module A { header "a.h" }

//--- a.h
#error blah

//--- tu.c
#include "a.h"

//--- cdb.json.in
[{
"directory": "DIR",
"file": "DIR/tu.c",
"command": "clang -c DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache"
}]

// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json
// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full > %t/deps.json
18 changes: 18 additions & 0 deletions clang/test/CodeGen/X86/x86_64-arguments.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), __aligned__(128)));
void f66(t66 a0) {
}

typedef long long t67 __attribute__((aligned (4)));
struct s67 {
int a;
t67 b;
};
// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 %x)
void f67(struct s67 x) {
}

typedef double t68 __attribute__((aligned (4)));
struct s68 {
int a;
t68 b;
};
// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x)
void f68(struct s68 x) {
}

/// The synthesized __va_list_tag does not have file/line fields.
// CHECK: = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__va_list_tag",
// CHECK-NOT: file:
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/ubsan-bitfield-conversion.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void foo1(int x) {
// CHECK-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
// CHECK-BITFIELD-CONVERSION: [[CONT]]:
// CHECK-NEXT: ret void
}
Expand All @@ -29,7 +29,7 @@ void foo2(int x) {
// CHECK-NEXT: [[BFRESULTSHL:%.*]] = shl i8 {{.*}}, 6
// CHECK-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 6
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
// CHECK-BITFIELD-CONVERSION: [[CONT]]:
// CHECK-NEXT: ret void
}
Expand All @@ -42,7 +42,7 @@ void foo3() {
// CHECK-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
// CHECK-BITFIELD-CONVERSION: [[CONT]]:
// CHECK-NEXT: ret void
}
Expand All @@ -55,7 +55,7 @@ void foo4(int x) {
// CHECK-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
// CHECK-BITFIELD-CONVERSION: [[CONT]]:
// CHECK-NEXT: ret void
}
82 changes: 41 additions & 41 deletions clang/test/CodeGenCUDA/offloading-entries.cu
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --global-value-regex ".omp_offloading.entry.*"
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --global-value-regex ".offloading.entry.*"
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fgpu-rdc \
// RUN: --offload-new-driver -emit-llvm -o - -x cuda %s | FileCheck \
// RUN: --check-prefix=CUDA %s
Expand All @@ -15,49 +15,49 @@
#include "Inputs/cuda.h"

//.
// CUDA: @.omp_offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00"
// CUDA: @.omp_offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z18__device_stub__foov, ptr @.omp_offloading.entry_name, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries", align 1
// CUDA: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00"
// CUDA: @.omp_offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z21__device_stub__kernelv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries", align 1
// CUDA: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00"
// CUDA: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "cuda_offloading_entries", align 1
// CUDA: @.omp_offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00"
// CUDA: @.omp_offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.omp_offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "cuda_offloading_entries", align 1
// CUDA: @.omp_offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00"
// CUDA: @.omp_offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.omp_offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "cuda_offloading_entries", align 1
// CUDA: @.offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00"
// CUDA: @.offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z18__device_stub__foov, ptr @.offloading.entry_name, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries", align 1
// CUDA: @.offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00"
// CUDA: @.offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z21__device_stub__kernelv, ptr @.offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries", align 1
// CUDA: @.offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00"
// CUDA: @.offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "cuda_offloading_entries", align 1
// CUDA: @.offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00"
// CUDA: @.offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "cuda_offloading_entries", align 1
// CUDA: @.offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00"
// CUDA: @.offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "cuda_offloading_entries", align 1
//.
// HIP: @.omp_offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00"
// HIP: @.omp_offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z3foov, ptr @.omp_offloading.entry_name, i64 0, i32 0, i32 0 }, section "hip_offloading_entries", align 1
// HIP: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00"
// HIP: @.omp_offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z6kernelv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "hip_offloading_entries", align 1
// HIP: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00"
// HIP: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "hip_offloading_entries", align 1
// HIP: @.omp_offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00"
// HIP: @.omp_offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.omp_offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "hip_offloading_entries", align 1
// HIP: @.omp_offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00"
// HIP: @.omp_offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.omp_offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "hip_offloading_entries", align 1
// HIP: @.offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00"
// HIP: @.offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z3foov, ptr @.offloading.entry_name, i64 0, i32 0, i32 0 }, section "hip_offloading_entries", align 1
// HIP: @.offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00"
// HIP: @.offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z6kernelv, ptr @.offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "hip_offloading_entries", align 1
// HIP: @.offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00"
// HIP: @.offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "hip_offloading_entries", align 1
// HIP: @.offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00"
// HIP: @.offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "hip_offloading_entries", align 1
// HIP: @.offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00"
// HIP: @.offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "hip_offloading_entries", align 1
//.
// CUDA-COFF: @.omp_offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00"
// CUDA-COFF: @.omp_offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z18__device_stub__foov, ptr @.omp_offloading.entry_name, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00"
// CUDA-COFF: @.omp_offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z21__device_stub__kernelv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00"
// CUDA-COFF: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.omp_offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00"
// CUDA-COFF: @.omp_offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.omp_offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.omp_offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00"
// CUDA-COFF: @.omp_offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.omp_offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00"
// CUDA-COFF: @.offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z18__device_stub__foov, ptr @.offloading.entry_name, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00"
// CUDA-COFF: @.offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z21__device_stub__kernelv, ptr @.offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00"
// CUDA-COFF: @.offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00"
// CUDA-COFF: @.offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "cuda_offloading_entries$OE", align 1
// CUDA-COFF: @.offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00"
// CUDA-COFF: @.offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "cuda_offloading_entries$OE", align 1
//.
// HIP-COFF: @.omp_offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00"
// HIP-COFF: @.omp_offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z3foov, ptr @.omp_offloading.entry_name, i64 0, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00"
// HIP-COFF: @.omp_offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z6kernelv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00"
// HIP-COFF: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.omp_offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00"
// HIP-COFF: @.omp_offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.omp_offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.omp_offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00"
// HIP-COFF: @.omp_offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.omp_offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00"
// HIP-COFF: @.offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z3foov, ptr @.offloading.entry_name, i64 0, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00"
// HIP-COFF: @.offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z6kernelv, ptr @.offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00"
// HIP-COFF: @.offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00"
// HIP-COFF: @.offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "hip_offloading_entries$OE", align 1
// HIP-COFF: @.offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00"
// HIP-COFF: @.offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "hip_offloading_entries$OE", align 1
//.
// CUDA-LABEL: @_Z18__device_stub__foov(
// CUDA-NEXT: entry:
Expand Down
14 changes: 14 additions & 0 deletions clang/test/CodeGenCXX/arm64ec-vectorcall.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %clang_cc1 -triple arm64ec-windows-msvc -emit-llvm -o - %s -verify

// ARM64EC doesn't support generating __vectorcall calls... but __vectorcall
// function types need to be distinct from __cdecl function types to support
// compiling the STL. Make sure we only diagnose constructs that actually
// require generating code.
void __vectorcall f1();
void f2(void __vectorcall p()) {}
void f2(void p()) {}
void __vectorcall (*f3)();
void __vectorcall f4(); // expected-error {{__vectorcall}}
void __vectorcall f5() { // expected-error {{__vectorcall}}
f4(); // expected-error{{__vectorcall}}
}
364 changes: 364 additions & 0 deletions clang/test/CodeGenCXX/control-flow-in-stmt-expr.cpp

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions clang/test/CodeGenCXX/ubsan-bitfield-conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ void foo1(int x) {
// CHECK-BITFIELD-CONVERSION-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-BITFIELD-CONVERSION-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
c.a = x;
// CHECK: store i8 %{{.*}}
// CHECK-BITFIELD-CONVERSION: [[BFRESULTSHL:%.*]] = shl i8 {{.*}}, 5
// CHECK-BITFIELD-CONVERSION-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-BITFIELD-CONVERSION-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
// CHECK-BITFIELD-CONVERSION: [[CONT]]:
// CHECK-NEXT: ret void
}
Expand All @@ -42,13 +42,13 @@ void foo2(int x) {
// CHECK-BITFIELD-CONVERSION: [[BFRESULTSHL:%.*]] = shl i8 {{.*}}, 6
// CHECK-BITFIELD-CONVERSION-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 6
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
c.b = x;
// CHECK: store i8 %{{.*}}
// CHECK-BITFIELD-CONVERSION: [[BFRESULTSHL:%.*]] = shl i8 {{.*}}, 6
// CHECK-BITFIELD-CONVERSION-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 6
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
// CHECK-BITFIELD-CONVERSION: [[CONT]]:
// CHECK-NEXT: ret void
}
Expand All @@ -61,14 +61,14 @@ void foo3() {
// CHECK-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
c.a++;
// CHECK: store i8 %{{.*}}
// CHECK-NEXT: [[BFRESULTSHL:%.*]] = shl i8 {{.*}}, 5
// CHECK-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
// CHECK-BITFIELD-CONVERSION: [[CONT]]:
// CHECK-NEXT: ret void
}
Expand All @@ -81,14 +81,14 @@ void foo4(int x) {
// CHECK-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
c.a += x;
// CHECK: store i8 %{{.*}}
// CHECK-NEXT: [[BFRESULTSHL:%.*]] = shl i8 {{.*}}, 5
// CHECK-NEXT: [[BFRESULTASHR:%.*]] = ashr i8 [[BFRESULTSHL]], 5
// CHECK-NEXT: [[BFRESULTCAST:%.*]] = sext i8 [[BFRESULTASHR]] to i32
// CHECK-BITFIELD-CONVERSION: call void @__ubsan_handle_implicit_conversion
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize !6
// CHECK-BITFIELD-CONVERSION-NEXT: br label %[[CONT:.*]], !nosanitize
// CHECK-BITFIELD-CONVERSION: [[CONT]]:
// CHECK-NEXT: ret void
}
93 changes: 93 additions & 0 deletions clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// RUN: %clang_cc1 --std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s

#include "Inputs/coroutine.h"

struct Printy {
Printy(const char *name) : name(name) {}
~Printy() {}
const char *name;
};

struct coroutine {
struct promise_type;
std::coroutine_handle<promise_type> handle;
~coroutine() {
if (handle) handle.destroy();
}
};

struct coroutine::promise_type {
coroutine get_return_object() {
return {std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};

struct Awaiter : std::suspend_always {
Printy await_resume() { return {"awaited"}; }
};

int foo() { return 2; }

coroutine ArrayInitCoro() {
// Verify that:
// - We do the necessary stores for array cleanups.
// - Array cleanups are called by await.cleanup.
// - We activate the cleanup after the first element and deactivate it in await.ready (see cleanup.isactive).

// CHECK-LABEL: define dso_local void @_Z13ArrayInitCorov
// CHECK: %arrayinit.endOfInit = alloca ptr, align 8
// CHECK: %cleanup.isactive = alloca i1, align 1
Printy arr[2] = {
Printy("a"),
// CHECK: %arrayinit.begin = getelementptr inbounds [2 x %struct.Printy], ptr %arr.reload.addr, i64 0, i64 0
// CHECK-NEXT: %arrayinit.begin.spill.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 10
// CHECK-NEXT: store ptr %arrayinit.begin, ptr %arrayinit.begin.spill.addr, align 8
// CHECK-NEXT: store i1 true, ptr %cleanup.isactive.reload.addr, align 1
// CHECK-NEXT: store ptr %arrayinit.begin, ptr %arrayinit.endOfInit.reload.addr, align 8
// CHECK-NEXT: call void @_ZN6PrintyC1EPKc(ptr noundef nonnull align 8 dereferenceable(8) %arrayinit.begin, ptr noundef @.str)
// CHECK-NEXT: %arrayinit.element = getelementptr inbounds %struct.Printy, ptr %arrayinit.begin, i64 1
// CHECK-NEXT: %arrayinit.element.spill.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 11
// CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.element.spill.addr, align 8
// CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.endOfInit.reload.addr, align 8
co_await Awaiter{}
// CHECK-NEXT: @_ZNSt14suspend_always11await_readyEv
// CHECK-NEXT: br i1 %{{.+}}, label %await.ready, label %CoroSave30
};
// CHECK: await.cleanup: ; preds = %AfterCoroSuspend{{.*}}
// CHECK-NEXT: br label %cleanup{{.*}}.from.await.cleanup

// CHECK: cleanup{{.*}}.from.await.cleanup: ; preds = %await.cleanup
// CHECK: br label %cleanup{{.*}}

// CHECK: await.ready:
// CHECK-NEXT: %arrayinit.element.reload.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 11
// CHECK-NEXT: %arrayinit.element.reload = load ptr, ptr %arrayinit.element.reload.addr, align 8
// CHECK-NEXT: call void @_ZN7Awaiter12await_resumeEv
// CHECK-NEXT: store i1 false, ptr %cleanup.isactive.reload.addr, align 1
// CHECK-NEXT: br label %cleanup{{.*}}.from.await.ready

// CHECK: cleanup{{.*}}: ; preds = %cleanup{{.*}}.from.await.ready, %cleanup{{.*}}.from.await.cleanup
// CHECK: %cleanup.is_active = load i1, ptr %cleanup.isactive.reload.addr, align 1
// CHECK-NEXT: br i1 %cleanup.is_active, label %cleanup.action, label %cleanup.done

// CHECK: cleanup.action:
// CHECK: %arraydestroy.isempty = icmp eq ptr %arrayinit.begin.reload{{.*}}, %{{.*}}
// CHECK-NEXT: br i1 %arraydestroy.isempty, label %arraydestroy.done{{.*}}, label %arraydestroy.body.from.cleanup.action
// Ignore rest of the array cleanup.
}

coroutine ArrayInitWithCoReturn() {
// CHECK-LABEL: define dso_local void @_Z21ArrayInitWithCoReturnv
// Verify that we start to emit the array destructor.
// CHECK: %arrayinit.endOfInit = alloca ptr, align 8
Printy arr[2] = {"a", ({
if (foo()) {
co_return;
}
"b";
})};
}
4 changes: 4 additions & 0 deletions clang/test/Driver/linker-wrapper-libs.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ int bar() { return weak; }
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.a %t.o -o a.out 2>&1 \
// RUN: | FileCheck %s --check-prefix=LIBRARY-RESOLVES

// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
Expand All @@ -66,6 +68,8 @@ int bar() { return weak; }
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.a %t.o -o a.out 2>&1 \
// RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL

// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
Expand Down
10 changes: 5 additions & 5 deletions clang/test/OpenMP/declare_target_link_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
// DEVICE: @c_decl_tgt_ref_ptr = weak global ptr null
// HOST: [[SIZES:@.+]] = private unnamed_addr constant [3 x i64] [i64 4, i64 4, i64 4]
// HOST: [[MAPTYPES:@.+]] = private unnamed_addr constant [3 x i64] [i64 35, i64 531, i64 531]
// HOST: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_ref_ptr\00"
// HOST: @.omp_offloading.entry.c_decl_tgt_ref_ptr = weak constant %struct.__tgt_offload_entry { ptr @c_decl_tgt_ref_ptr, ptr @.omp_offloading.entry_name, i64 8, i32 1, i32 0 }, section "omp_offloading_entries", align 1
// HOST-COFF: @.omp_offloading.entry.{{.*}} = weak constant %struct.__tgt_offload_entry { ptr @.{{.*}}, ptr @.{{.*}}, i64 0, i32 0, i32 0 }, section "omp_offloading_entries$OE", align 1
// HOST: @.offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_ref_ptr\00"
// HOST: @.offloading.entry.c_decl_tgt_ref_ptr = weak constant %struct.__tgt_offload_entry { ptr @c_decl_tgt_ref_ptr, ptr @.offloading.entry_name, i64 8, i32 1, i32 0 }, section "omp_offloading_entries", align 1
// HOST-COFF: @.offloading.entry.{{.*}} = weak constant %struct.__tgt_offload_entry { ptr @.{{.*}}, ptr @.{{.*}}, i64 0, i32 0, i32 0 }, section "omp_offloading_entries$OE", align 1
// DEVICE-NOT: internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_{{.*}}_decl_tgt_ref_ptr\00"
// HOST: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"_{{.*}}d_{{.*}}_decl_tgt_ref_ptr\00"
// HOST: @.omp_offloading.entry.[[D_PTR]] = weak constant %struct.__tgt_offload_entry { ptr @[[D_PTR]], ptr @.omp_offloading.entry_name{{.*}}
// HOST: @.offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"_{{.*}}d_{{.*}}_decl_tgt_ref_ptr\00"
// HOST: @.offloading.entry.[[D_PTR]] = weak constant %struct.__tgt_offload_entry { ptr @[[D_PTR]], ptr @.offloading.entry_name{{.*}}

extern int c;
#pragma omp declare target link(c)
Expand Down
8 changes: 4 additions & 4 deletions clang/test/OpenMP/declare_target_visibility_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ class C {
// HOST: @[[X:.+]] = internal global i32 0, align 4
// HOST: @y = hidden global i32 0
// HOST: @z = global i32 0
// HOST-NOT: @.omp_offloading.entry.c
// HOST-NOT: @.omp_offloading.entry.x
// HOST-NOT: @.omp_offloading.entry.y
// HOST: @.omp_offloading.entry.z
// HOST-NOT: @.offloading.entry.c
// HOST-NOT: @.offloading.entry.x
// HOST-NOT: @.offloading.entry.y
// HOST: @.offloading.entry.z
C() : x(0) {}

int x;
Expand Down
48 changes: 24 additions & 24 deletions clang/test/OpenMP/target_codegen_registration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,54 +119,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i

// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME1]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR1]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME1]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR1]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME2]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR2]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME2]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR2]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME3]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR3]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME3]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR3]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME4]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR4]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME4]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR4]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME5]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR5]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME5]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR5]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME6]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR6]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME6]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR6]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME7]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR7]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME7]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR7]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME8]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR8]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME8]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR8]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME9]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR9]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME9]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR9]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME10]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR10]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME10]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR10]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME11]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR11]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME11]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR11]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
// CHECK-DAG: @.omp_offloading.entry.[[NAME12]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR12]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// CHECK-DAG: @.offloading.entry.[[NAME12]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR12]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1

// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME1]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR1]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME1]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR1]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME2]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR2]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME2]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR2]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME3]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR3]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME3]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR3]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME4]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR4]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME4]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR4]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME5]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR5]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME5]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR5]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME6]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR6]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME6]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR6]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME7]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR7]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME7]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR7]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME8]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR8]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME8]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR8]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME9]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR9]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME9]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR9]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME10]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR10]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME10]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR10]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME11]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR11]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME11]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR11]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
// TCHECK-DAG: @.omp_offloading.entry.[[NAME12]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR12]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// TCHECK-DAG: @.offloading.entry.[[NAME12]] = weak{{.*}} constant [[ENTTY]] { ptr @{{.*}}, ptr [[NAMEPTR12]], i[[SZ]] 0, i32 0, i32 0 }, section "omp_offloading_entries", align 1

// We have 4 initializers, one for the 500 priority, another one for 501, or more for the default priority, and the last one for the offloading registration function.
// CHECK: @llvm.global_ctors = appending global [3 x { i32, ptr, ptr }] [
Expand Down
8 changes: 4 additions & 4 deletions clang/test/OpenMP/target_indirect_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
//.
// HOST: @[[VAR:.+]] = global i8 0, align 1
// HOST: @[[FOO_ENTRY_NAME:.+]] = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[FOO_NAME:__omp_offloading_[0-9a-z]+_[0-9a-z]+_foo_l[0-9]+]]\00"
// HOST: @.omp_offloading.entry.[[FOO_NAME]] = weak constant %struct.__tgt_offload_entry { ptr @_Z3foov, ptr @[[FOO_ENTRY_NAME]], i64 8, i32 8, i32 0 }, section "omp_offloading_entries", align 1
// HOST: @.offloading.entry.[[FOO_NAME]] = weak constant %struct.__tgt_offload_entry { ptr @_Z3foov, ptr @[[FOO_ENTRY_NAME]], i64 8, i32 8, i32 0 }, section "omp_offloading_entries", align 1
// HOST: @[[BAZ_ENTRY_NAME:.+]] = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[BAZ_NAME:__omp_offloading_[0-9a-z]+_[0-9a-z]+_baz_l[0-9]+]]\00"
// HOST: @.omp_offloading.entry.[[BAZ_NAME]] = weak constant %struct.__tgt_offload_entry { ptr @_Z3bazv, ptr @[[BAZ_ENTRY_NAME]], i64 8, i32 8, i32 0 }, section "omp_offloading_entries", align 1
// HOST: @.offloading.entry.[[BAZ_NAME]] = weak constant %struct.__tgt_offload_entry { ptr @_Z3bazv, ptr @[[BAZ_ENTRY_NAME]], i64 8, i32 8, i32 0 }, section "omp_offloading_entries", align 1
// HOST: @[[VAR_ENTRY_NAME:.+]] = internal unnamed_addr constant [4 x i8] c"var\00"
// HOST: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @[[VAR]], ptr @[[VAR_ENTRY_NAME]], i64 1, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// HOST: @.offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @[[VAR]], ptr @[[VAR_ENTRY_NAME]], i64 1, i32 0, i32 0 }, section "omp_offloading_entries", align 1
// HOST: @[[BAR_ENTRY_NAME:.+]] = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[BAR_NAME:__omp_offloading_[0-9a-z]+_[0-9a-z]+_bar_l[0-9]+]]\00"
// HOST: @.omp_offloading.entry.[[BAR_NAME]] = weak constant %struct.__tgt_offload_entry { ptr @_ZL3barv, ptr @[[BAR_ENTRY_NAME]], i64 8, i32 8, i32 0 }, section "omp_offloading_entries", align 1
// HOST: @.offloading.entry.[[BAR_NAME]] = weak constant %struct.__tgt_offload_entry { ptr @_ZL3barv, ptr @[[BAR_ENTRY_NAME]], i64 8, i32 8, i32 0 }, section "omp_offloading_entries", align 1
//.
// DEVICE: @[[FOO_NAME:__omp_offloading_[0-9a-z]+_[0-9a-z]+_foo_l[0-9]+]] = protected addrspace(1) constant ptr @_Z3foov
// DEVICE: @[[BAZ_NAME:__omp_offloading_[0-9a-z]+_[0-9a-z]+_baz_l[0-9]+]] = protected addrspace(1) constant ptr @_Z3bazv
Expand Down
20 changes: 6 additions & 14 deletions clang/test/ParserOpenACC/parse-clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,45 +173,37 @@ void DefaultClause() {
#pragma acc serial default), seq
for(;;){}

// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+1{{expected identifier}}
#pragma acc serial default()
for(;;){}

// expected-error@+3{{expected identifier}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default() seq
for(;;){}

// expected-error@+3{{expected identifier}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default(), seq
for(;;){}

// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+1{{invalid value for 'default' clause; expected 'present' or 'none'}}
#pragma acc serial default(invalid)
for(;;){}

// expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default(auto) seq
for(;;){}

// expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default(invalid), seq
for(;;){}

// expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
#pragma acc serial default(none)
for(;;){}

// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default(present), seq
for(;;){}
Expand Down
6 changes: 5 additions & 1 deletion clang/test/Sema/aarch64-incompat-sm-builtin-calls.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -fsyntax-only -verify %s
// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -Waarch64-sme-attributes -fsyntax-only -verify %s

// REQUIRES: aarch64-registered-target

Expand Down Expand Up @@ -33,6 +33,7 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming
return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b);
Expand All @@ -48,6 +49,7 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin
return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b);
Expand All @@ -68,6 +70,7 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_
return svadd_n_f64_m(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) {
// expected-no-warning
return svadd_n_f64_m(pg, a, b);
Expand All @@ -83,6 +86,7 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming {
return svmul_lane_s16(op1, op2, 0);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) {
// expected-no-warning
return svmul_lane_s16(op1, op2, 0);
Expand Down
136 changes: 134 additions & 2 deletions clang/test/Sema/aarch64-sme-func-attrs.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify=expected-cpp -x c++ %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify=expected-cpp -x c++ %s

// Valid attributes

Expand Down Expand Up @@ -496,3 +496,135 @@ void fmv_caller() {
just_fine();
incompatible_locally_streaming();
}

void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { }

__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; }

void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible { }

__SVInt8_t sme_streaming_compatible_returns_vl(void) __arm_streaming_compatible { __SVInt8_t r; return r; }

void sme_no_streaming_with_vl_arg(__SVInt8_t a) { }

__SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; }

// expected-warning@+2 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { }

// expected-warning@+2 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; }

void sme_no_streaming_calling_streaming_with_vl_args() {
__SVInt8_t a;
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sme_streaming_with_vl_arg(a);
}

void sme_no_streaming_calling_streaming_with_return_vl() {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
__SVInt8_t r = sme_streaming_returns_vl();
}

void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming {
__SVInt8_t a;
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sme_no_streaming_with_vl_arg(a);
}

void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
__SVInt8_t r = sme_no_streaming_returns_vl();
}

void sme_no_streaming_calling_streaming_with_vl_args_param(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sc(arg);
}

__SVInt8_t sme_no_streaming_calling_streaming_return_vl_param(__SVInt8_t (*s)(void) __arm_streaming) {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
return s();
}

void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sme_streaming_with_vl_arg(arg);
}

void sme_streaming_compatible_calling_sme_streaming_return_vl(void) __arm_streaming_compatible {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
__SVInt8_t r = sme_streaming_returns_vl();
}

void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sme_no_streaming_with_vl_arg(arg);
}

void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) __arm_streaming_compatible {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
__SVInt8_t r = sme_no_streaming_returns_vl();
}

void sme_streaming_calling_streaming(__SVInt8_t arg, void (*s)( __SVInt8_t arg) __arm_streaming) __arm_streaming {
s(arg);
}

__SVInt8_t sme_streaming_calling_streaming_return_vl(__SVInt8_t (*s)(void) __arm_streaming) __arm_streaming {
return s();
}

void sme_streaming_calling_streaming_with_vl_args(__SVInt8_t a) __arm_streaming {
sme_streaming_with_vl_arg(a);
}

void sme_streaming_calling_streaming_with_return_vl(void) __arm_streaming {
__SVInt8_t r = sme_streaming_returns_vl();
}

void sme_streaming_calling_streaming_compatible_with_vl_args(__SVInt8_t a) __arm_streaming {
sme_streaming_compatible_with_vl_arg(a);
}

void sme_streaming_calling_streaming_compatible_with_return_vl(void) __arm_streaming {
__SVInt8_t r = sme_streaming_compatible_returns_vl();
}

void sme_no_streaming_calling_streaming_compatible_with_vl_args() {
__SVInt8_t a;
sme_streaming_compatible_with_vl_arg(a);
}

void sme_no_streaming_calling_streaming_compatible_with_return_vl() {
__SVInt8_t r = sme_streaming_compatible_returns_vl();
}

void sme_no_streaming_calling_non_streaming_compatible_with_vl_args() {
__SVInt8_t a;
sme_no_streaming_with_vl_arg(a);
}

void sme_no_streaming_calling_non_streaming_compatible_with_return_vl() {
__SVInt8_t r = sme_no_streaming_returns_vl();
}

void sme_streaming_compatible_calling_streaming_compatible_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
sme_streaming_compatible_with_vl_arg(arg);
}

void sme_streaming_compatible_calling_streaming_compatible_with_return_vl(void) __arm_streaming_compatible {
__SVInt8_t r = sme_streaming_compatible_returns_vl();
}
1 change: 1 addition & 0 deletions clang/test/SemaCXX/type-traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,7 @@ void is_layout_compatible(int n)
// expected-error@-1 {{variable length arrays are not supported in '__is_layout_compatible'}}
static_assert(!__is_layout_compatible(int[n], int[n]));
// expected-error@-1 {{variable length arrays are not supported in '__is_layout_compatible'}}
// expected-error@-2 {{variable length arrays are not supported in '__is_layout_compatible'}}
static_assert(__is_layout_compatible(int&, int&));
static_assert(!__is_layout_compatible(int&, char&));
static_assert(__is_layout_compatible(void(int), void(int)));
Expand Down
14 changes: 10 additions & 4 deletions clang/test/SemaOpenACC/compute-construct-ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ void NormalFunc() {
// CHECK-LABEL: NormalFunc
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: default(none)
// CHECK-NEXT: CompoundStmt
#pragma acc parallel
#pragma acc parallel default(none)
{
#pragma acc parallel
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: default(present)
// CHECK-NEXT: CompoundStmt
#pragma acc parallel
#pragma acc parallel default(present)
{}
}
// FIXME: Add a test once we have clauses for this.
Expand Down Expand Up @@ -50,12 +52,12 @@ void NormalFunc() {

template<typename T>
void TemplFunc() {
#pragma acc parallel
#pragma acc parallel default(none)
{
typename T::type I;
}

#pragma acc serial
#pragma acc serial default(present)
{
typename T::type I;
}
Expand All @@ -72,10 +74,12 @@ void TemplFunc() {
// CHECK-NEXT: FunctionDecl
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: default(none)
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl{{.*}} I 'typename T::type'
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
// CHECK-NEXT: default(present)
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl{{.*}} I 'typename T::type'
Expand All @@ -91,10 +95,12 @@ void TemplFunc() {
// CHECK-NEXT: CXXRecord
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: default(none)
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int'
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
// CHECK-NEXT: default(present)
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int'
Expand Down
74 changes: 74 additions & 0 deletions clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s

// Test this with PCH.
// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s
// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s

#ifndef PCH_HELPER
#define PCH_HELPER
void NormalFunc() {
// CHECK: FunctionDecl{{.*}}NormalFunc
// CHECK-NEXT: CompoundStmt
#pragma acc parallel default(none)
while(true);
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel
// CHECK-NEXT: default(none)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt

#pragma acc serial default(present)
while(true);
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial
// CHECK-NEXT: default(present)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt
}

template<typename T>
void TemplFunc() {
// CHECK: FunctionTemplateDecl{{.*}}TemplFunc
// CHECK-NEXT: TemplateTypeParmDecl

// Match the prototype:
// CHECK-NEXT: FunctionDecl{{.*}}TemplFunc
// CHECK-NEXT: CompoundStmt

#pragma acc kernels default(none)
while(true);
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels
// CHECK-NEXT: default(none)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt

#pragma acc parallel default(present)
while(true);
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel
// CHECK-NEXT: default(present)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt

// Match the instantiation:
// CHECK: FunctionDecl{{.*}}TemplFunc{{.*}}implicit_instantiation
// CHECK-NEXT: TemplateArgument type 'int'
// CHECK-NEXT: BuiltinType
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels
// CHECK-NEXT: default(none)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel
// CHECK-NEXT: default(present)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt
}

void Instantiate() {
TemplFunc<int>();
}
#endif
Loading