18 changes: 8 additions & 10 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19528,16 +19528,6 @@ static bool captureInLambda(LambdaScopeInfo *LSI, ValueDecl *Var,
ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
}

BindingDecl *BD = dyn_cast<BindingDecl>(Var);
// FIXME: We should support capturing structured bindings in OpenMP.
if (!Invalid && BD && S.LangOpts.OpenMP) {
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_capture_binding_openmp) << Var;
S.Diag(Var->getLocation(), diag::note_entity_declared_at) << Var;
}
Invalid = true;
}

if (BuildAndDiagnose && S.Context.getTargetInfo().getTriple().isWasm() &&
CaptureType.getNonReferenceType().isWebAssemblyReferenceType()) {
S.Diag(Loc, diag::err_wasm_ca_reference) << 0;
Expand Down Expand Up @@ -19879,6 +19869,14 @@ bool Sema::tryCaptureVariable(
// just break here. Similarly, global variables that are captured in a
// target region should not be captured outside the scope of the region.
if (RSI->CapRegionKind == CR_OpenMP) {
// FIXME: We should support capturing structured bindings in OpenMP.
if (isa<BindingDecl>(Var)) {
if (BuildAndDiagnose) {
Diag(ExprLoc, diag::err_capture_binding_openmp) << Var;
Diag(Var->getLocation(), diag::note_entity_declared_at) << Var;
}
return true;
}
OpenMPClauseKind IsOpenMPPrivateDecl = isOpenMPPrivateDecl(
Var, RSI->OpenMPLevel, RSI->OpenMPCaptureLevel);
// If the variable is private (i.e. not captured) and has variably
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9113,9 +9113,7 @@ Sema::BuildExprRequirement(

auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));

TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args);
MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray(),
/*Final=*/false);
MultiLevelTemplateArgumentList MLTAL(Param, Args, /*Final=*/false);
MLTAL.addOuterRetainedLevels(TPL->getDepth());
const TypeConstraint *TC = Param->getTypeConstraint();
assert(TC && "Type Constraint cannot be null here");
Expand Down
20 changes: 8 additions & 12 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4843,9 +4843,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
// the set of specializations, based on the closest partial specialization
// that it represents. That is,
VarDecl *InstantiationPattern = Template->getTemplatedDecl();
TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
CanonicalConverted);
TemplateArgumentList *InstantiationArgs = &TemplateArgList;
const TemplateArgumentList *PartialSpecArgs = nullptr;
bool AmbiguousPartialSpec = false;
typedef PartialSpecMatchResult MatchResult;
SmallVector<MatchResult, 4> Matched;
Expand All @@ -4866,7 +4864,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
TemplateDeductionInfo Info(FailedCandidates.getLocation());

if (TemplateDeductionResult Result =
DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
DeduceTemplateArguments(Partial, CanonicalConverted, Info)) {
// Store the failed-deduction information for use in diagnostics, later.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate().set(
Expand Down Expand Up @@ -4919,7 +4917,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,

// Instantiate using the best variable template partial specialization.
InstantiationPattern = Best->Partial;
InstantiationArgs = Best->Args;
PartialSpecArgs = Best->Args;
} else {
// -- If no match is found, the instantiation is generated
// from the primary template.
Expand All @@ -4931,7 +4929,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
// in DoMarkVarDeclReferenced().
// FIXME: LateAttrs et al.?
VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation(
Template, InstantiationPattern, *InstantiationArgs, TemplateArgs,
Template, InstantiationPattern, PartialSpecArgs, TemplateArgs,
CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/);
if (!Decl)
return true;
Expand All @@ -4952,7 +4950,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,

if (VarTemplatePartialSpecializationDecl *D =
dyn_cast<VarTemplatePartialSpecializationDecl>(InstantiationPattern))
Decl->setInstantiationOf(D, InstantiationArgs);
Decl->setInstantiationOf(D, PartialSpecArgs);

checkSpecializationReachability(TemplateNameLoc, Decl);

Expand Down Expand Up @@ -6257,8 +6255,6 @@ bool Sema::CheckTemplateArgumentList(
TemplateArgs = std::move(NewArgs);

if (!PartialTemplateArgs) {
TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack,
CanonicalConverted);
// Setup the context/ThisScope for the case where we are needing to
// re-instantiate constraints outside of normal instantiation.
DeclContext *NewContext = Template->getDeclContext();
Expand All @@ -6278,7 +6274,7 @@ bool Sema::CheckTemplateArgumentList(
CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr);

MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
Template, NewContext, /*Final=*/false, &StackTemplateArgs,
Template, NewContext, /*Final=*/false, CanonicalConverted,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConceptInstantiation=*/true);
Expand Down Expand Up @@ -9782,8 +9778,8 @@ bool Sema::CheckFunctionTemplateSpecialization(
// specialization, with the template arguments from the previous
// specialization.
// Take copies of (semantic and syntactic) template argument lists.
const TemplateArgumentList* TemplArgs = new (Context)
TemplateArgumentList(Specialization->getTemplateSpecializationArgs());
const TemplateArgumentList *TemplArgs = TemplateArgumentList::CreateCopy(
Context, Specialization->getTemplateSpecializationArgs()->asArray());
FD->setFunctionTemplateSpecialization(
Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr,
SpecInfo->getTemplateSpecializationKind(),
Expand Down
70 changes: 29 additions & 41 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2514,17 +2514,6 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
return Sema::TDK_Success;
}

static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
const TemplateArgumentList &ParamList,
const TemplateArgumentList &ArgList,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
return DeduceTemplateArguments(S, TemplateParams, ParamList.asArray(),
ArgList.asArray(), Info, Deduced,
/*NumberOfArgumentsMustMatch=*/false);
}

/// Determine whether two template arguments are the same.
static bool isSameTemplateArg(ASTContext &Context,
TemplateArgument X,
Expand Down Expand Up @@ -2945,21 +2934,22 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
Template->getAssociatedConstraints(AssociatedConstraints);

bool NeedsReplacement = DeducedArgsNeedReplacement(Template);
TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack,
CanonicalDeducedArgs};
std::optional<ArrayRef<TemplateArgument>> Innermost;
// If we don't need to replace the deduced template arguments,
// we can add them immediately as the inner-most argument list.
if (!DeducedArgsNeedReplacement(Template))
Innermost = CanonicalDeducedArgs;

MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
Template, Template->getDeclContext(), /*Final=*/false,
/*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL,
Template, Template->getDeclContext(), /*Final=*/false, Innermost,
/*RelativeToPrimary=*/true, /*Pattern=*/
nullptr, /*ForConstraintInstantiation=*/true);

// getTemplateInstantiationArgs picks up the non-deduced version of the
// template args when this is a variable template partial specialization and
// not class-scope explicit specialization, so replace with Deduced Args
// instead of adding to inner-most.
if (NeedsReplacement)
if (!Innermost)
MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);

if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
Expand All @@ -2980,7 +2970,7 @@ static std::enable_if_t<IsPartialSpecialization<T>::value,
Sema::TemplateDeductionResult>
FinishTemplateArgumentDeduction(
Sema &S, T *Partial, bool IsPartialOrdering,
const TemplateArgumentList &TemplateArgs,
ArrayRef<TemplateArgument> TemplateArgs,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info) {
// Unevaluated SFINAE context.
Expand Down Expand Up @@ -3073,7 +3063,7 @@ FinishTemplateArgumentDeduction(
// FIXME: Factor out duplication with partial specialization version above.
static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
Sema &S, TemplateDecl *Template, bool PartialOrdering,
const TemplateArgumentList &TemplateArgs,
ArrayRef<TemplateArgument> TemplateArgs,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info) {
// Unevaluated SFINAE context.
Expand Down Expand Up @@ -3122,7 +3112,7 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
/// partial specialization per C++ [temp.class.spec.match].
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
ArrayRef<TemplateArgument> TemplateArgs,
TemplateDeductionInfo &Info) {
if (Partial->isInvalidDecl())
return TDK_Invalid;
Expand All @@ -3144,11 +3134,10 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,

SmallVector<DeducedTemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result
= ::DeduceTemplateArguments(*this,
Partial->getTemplateParameters(),
Partial->getTemplateArgs(),
TemplateArgs, Info, Deduced))
if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
*this, Partial->getTemplateParameters(),
Partial->getTemplateArgs().asArray(), TemplateArgs, Info, Deduced,
/*NumberOfArgumentsMustMatch=*/false))
return Result;

SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
Expand All @@ -3174,7 +3163,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
/// partial specialization per C++ [temp.class.spec.match].
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
ArrayRef<TemplateArgument> TemplateArgs,
TemplateDeductionInfo &Info) {
if (Partial->isInvalidDecl())
return TDK_Invalid;
Expand All @@ -3197,8 +3186,9 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
SmallVector<DeducedTemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
*this, Partial->getTemplateParameters(), Partial->getTemplateArgs(),
TemplateArgs, Info, Deduced))
*this, Partial->getTemplateParameters(),
Partial->getTemplateArgs().asArray(), TemplateArgs, Info, Deduced,
/*NumberOfArgumentsMustMatch=*/false))
return Result;

SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
Expand Down Expand Up @@ -3427,15 +3417,15 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
// specification.
SmallVector<QualType, 4> ExceptionStorage;
if (getLangOpts().CPlusPlus17 &&
SubstExceptionSpec(Function->getLocation(), EPI.ExceptionSpec,
ExceptionStorage,
getTemplateInstantiationArgs(
FunctionTemplate, nullptr, /*Final=*/true,
/*Innermost=*/SugaredExplicitArgumentList,
/*RelativeToPrimary=*/false,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/false,
/*SkipForSpecialization=*/true)))
SubstExceptionSpec(
Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage,
getTemplateInstantiationArgs(
FunctionTemplate, nullptr, /*Final=*/true,
/*Innermost=*/SugaredExplicitArgumentList->asArray(),
/*RelativeToPrimary=*/false,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/false,
/*SkipForSpecialization=*/true)))
return TDK_SubstitutionFailure;

*FunctionType = BuildFunctionType(ResultType, ParamTypes,
Expand Down Expand Up @@ -5802,10 +5792,8 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
bool AtLeastAsSpecialized;
S.runWithSufficientStackSpace(Info.getLocation(), [&] {
AtLeastAsSpecialized = !FinishTemplateArgumentDeduction(
S, P2, /*IsPartialOrdering=*/true,
TemplateArgumentList(TemplateArgumentList::OnStack,
TST1->template_arguments()),
Deduced, Info);
S, P2, /*IsPartialOrdering=*/true, TST1->template_arguments(), Deduced,
Info);
});
return AtLeastAsSpecialized;
}
Expand Down
11 changes: 6 additions & 5 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ Response HandleGenericDeclContext(const Decl *CurDecl) {

MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
const NamedDecl *ND, const DeclContext *DC, bool Final,
const TemplateArgumentList *Innermost, bool RelativeToPrimary,
std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
const FunctionDecl *Pattern, bool ForConstraintInstantiation,
bool SkipForSpecialization) {
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
Expand All @@ -352,8 +352,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
CurDecl = Decl::castFromDeclContext(DC);

if (Innermost) {
Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND),
Innermost->asArray(), Final);
Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost,
Final);
// Populate placeholder template arguments for TemplateTemplateParmDecls.
// This is essential for the case e.g.
//
Expand Down Expand Up @@ -3656,7 +3656,8 @@ bool Sema::usesPartialOrExplicitSpecialization(
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
TemplateDeductionInfo Info(Loc);
if (!DeduceTemplateArguments(PartialSpecs[I],
ClassTemplateSpec->getTemplateArgs(), Info))
ClassTemplateSpec->getTemplateArgs().asArray(),
Info))
return true;
}

Expand Down Expand Up @@ -3701,7 +3702,7 @@ getPatternForClassTemplateSpecialization(
ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
Partial, ClassTemplateSpec->getTemplateArgs(), Info)) {
Partial, ClassTemplateSpec->getTemplateArgs().asArray(), Info)) {
// Store the failed-deduction information for use in diagnostics, later.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate().set(
Expand Down
27 changes: 15 additions & 12 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4656,9 +4656,10 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
//
// template<typename T>
// A<T> Foo(int a = A<T>::FooImpl());
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
FD, FD->getLexicalDeclContext(), /*Final=*/false, nullptr,
/*RelativeToPrimary=*/true);
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true);

if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
return true;
Expand Down Expand Up @@ -4696,9 +4697,10 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
Sema::ContextRAII savedContext(*this, Decl);
LocalInstantiationScope Scope(*this);

MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
Decl, Decl->getLexicalDeclContext(), /*Final=*/false, nullptr,
/*RelativeToPrimary*/ true);
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Decl, Decl->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary*/ true);

// FIXME: We can't use getTemplateInstantiationPattern(false) in general
// here, because for a non-defining friend declaration in a class template,
Expand Down Expand Up @@ -5140,8 +5142,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
SetDeclDefaulted(Function, PatternDecl->getLocation());
} else {
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
Function, Function->getLexicalDeclContext(), /*Final=*/false, nullptr,
false, PatternDecl);
Function, Function->getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt, false, PatternDecl);

// Substitute into the qualifier; we can get a substitution failure here
// through evil use of alias templates.
Expand Down Expand Up @@ -5211,7 +5213,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,

VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
VarTemplateDecl *VarTemplate, VarDecl *FromVar,
const TemplateArgumentList &TemplateArgList,
const TemplateArgumentList *PartialSpecArgs,
const TemplateArgumentListInfo &TemplateArgsInfo,
SmallVectorImpl<TemplateArgument> &Converted,
SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs,
Expand All @@ -5236,14 +5238,15 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
MultiLevelTemplateArgumentList MultiLevelList;
if (auto *PartialSpec =
dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar)) {
assert(PartialSpecArgs);
IsMemberSpec = PartialSpec->isMemberSpecialization();
MultiLevelList.addOuterTemplateArguments(
PartialSpec, TemplateArgList.asArray(), /*Final=*/false);
PartialSpec, PartialSpecArgs->asArray(), /*Final=*/false);
} else {
assert(VarTemplate == FromVar->getDescribedVarTemplate());
IsMemberSpec = VarTemplate->isMemberSpecialization();
MultiLevelList.addOuterTemplateArguments(
VarTemplate, TemplateArgList.asArray(), /*Final=*/false);
MultiLevelList.addOuterTemplateArguments(VarTemplate, Converted,
/*Final=*/false);
}
if (!IsMemberSpec)
FromVar = FromVar->getFirstDecl();
Expand Down
10 changes: 4 additions & 6 deletions clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class HTMLDiagnostics : public PathDiagnosticConsumer {
const Preprocessor &PP;
const bool SupportsCrossFileDiagnostics;
llvm::StringSet<> EmittedHashes;
html::RelexRewriteCacheRef RewriterCache =
html::instantiateRelexRewriteCache();

public:
HTMLDiagnostics(PathDiagnosticConsumerOptions DiagOpts,
Expand Down Expand Up @@ -309,10 +311,6 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
return;
}

// FIXME: This causes each file to be re-parsed and syntax-highlighted
// and macro-expanded separately for each report. We could cache such rewrites
// across all reports and only re-do the part that's actually different:
// the warning/note bubbles.
std::string report = GenerateHTML(D, R, SMgr, path, declName.c_str());
if (report.empty()) {
llvm::errs() << "warning: no diagnostics generated for main file.\n";
Expand Down Expand Up @@ -882,8 +880,8 @@ void HTMLDiagnostics::RewriteFile(Rewriter &R, const PathPieces &path,
// If we have a preprocessor, relex the file and syntax highlight.
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
html::SyntaxHighlight(R, FID, PP);
html::HighlightMacros(R, FID, PP);
html::SyntaxHighlight(R, FID, PP, RewriterCache);
html::HighlightMacros(R, FID, PP, RewriterCache);
}

void HTMLDiagnostics::HandlePiece(Rewriter &R, FileID BugFileID,
Expand Down
40 changes: 40 additions & 0 deletions clang/test/AST/Interp/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,43 @@ const intptr_t L = (intptr_t)(&(yy->y)); // expected-error {{not a compile-time
const ptrdiff_t m = &m + 137 - &m;
_Static_assert(m == 137, ""); // pedantic-ref-warning {{GNU extension}} \
// pedantic-expected-warning {{GNU extension}}

/// from test/Sema/switch.c, used to cause an assertion failure.
void f (int z) {
while (z) {
default: z--; // expected-error {{'default' statement not in switch}} \
// pedantic-expected-error {{'default' statement not in switch}} \
// ref-error {{'default' statement not in switch}} \
// pedantic-ref-error {{'default' statement not in switch}}
}
}

int expr;
int chooseexpr[__builtin_choose_expr(1, 1, expr)];

int somefunc(int i) {
return (i, 65537) * 65537; // expected-warning {{left operand of comma operator has no effect}} \
// expected-warning {{overflow in expression; result is 131073}} \
// pedantic-expected-warning {{left operand of comma operator has no effect}} \
// pedantic-expected-warning {{overflow in expression; result is 131073}} \
// ref-warning {{left operand of comma operator has no effect}} \
// ref-warning {{overflow in expression; result is 131073}} \
// pedantic-ref-warning {{left operand of comma operator has no effect}} \
// pedantic-ref-warning {{overflow in expression; result is 131073}}

}

/// FIXME: The following test is incorrect in the new interpreter.
/// The null pointer returns 16 from its getIntegerRepresentation().
#pragma clang diagnostic ignored "-Wpointer-to-int-cast"
struct ArrayStruct {
char n[1];
};
char name2[(int)&((struct ArrayStruct*)0)->n]; // expected-warning {{folded to constant array}} \
// pedantic-expected-warning {{folded to constant array}} \
// ref-warning {{folded to constant array}} \
// pedantic-ref-warning {{folded to constant array}}
_Static_assert(sizeof(name2) == 0, ""); // expected-error {{failed}} \
// expected-note {{evaluates to}} \
// pedantic-expected-error {{failed}} \
// pedantic-expected-note {{evaluates to}}
29 changes: 29 additions & 0 deletions clang/test/Analysis/html_diagnostics/counter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: rm -fR %t
// RUN: mkdir %t
// RUN: %clang_analyze_cc1 -analyzer-checker=core \
// RUN: -analyzer-output=html -o %t -verify %s
// RUN: grep -v CHECK %t/report-*.html | FileCheck %s


void foo() {
int *x = 0;
*x = __COUNTER__; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}

void bar() {
int *y;
*y = __COUNTER__; // expected-warning{{Dereference of undefined pointer value (loaded from variable 'y')}}
}

// The checks below confirm that both reports have the same values for __COUNTER__.
//
// FIXME: The correct values are (0, 1, 0, 1). Because we re-lex the file in order
// to detect macro expansions for HTML report purposes, they turn into (2, 3, 2, 3)
// by the time we emit HTML. But at least it's better than (2, 3, 4, 5)
// which would have been the case if we re-lexed the file *each* time we
// emitted an HTML report.

// CHECK: <span class='macro'>__COUNTER__<span class='macro_popup'>2</span></span>
// CHECK: <span class='macro'>__COUNTER__<span class='macro_popup'>3</span></span>
// CHECK: <span class='macro'>__COUNTER__<span class='macro_popup'>2</span></span>
// CHECK: <span class='macro'>__COUNTER__<span class='macro_popup'>3</span></span>
6 changes: 6 additions & 0 deletions clang/test/CXX/temp/p3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ template<typename T> struct B { } f(); // expected-error {{expected ';' after st
template<typename T> struct C { } // expected-error {{expected ';' after struct}}

A<int> c;

struct D {
template<typename T> static const int x = 0, f(); // expected-error {{can only declare a single entity}}

template<typename T> static const int g(), y = 0; // expected-error {{can only declare a single entity}}
};
16 changes: 12 additions & 4 deletions clang/test/CodeGen/RISCV/riscv-inline-asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,16 @@ void test_A(int *p) {
asm volatile("" :: "A"(*p));
}

void test_S(void) {
// CHECK-LABEL: define{{.*}} void @test_S()
// CHECK: call void asm sideeffect "", "S"(ptr nonnull @f)
asm volatile("" :: "S"(&f));
extern int var, arr[2][2];
struct Pair { int a, b; } pair;

// CHECK-LABEL: test_s(
// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s"(ptr nonnull @var, ptr nonnull getelementptr inbounds ([2 x [2 x i32]], ptr @arr, {{.*}}), ptr nonnull @test_s)
// CHECK: call void asm sideeffect "// $0", "s"(ptr nonnull getelementptr inbounds (%struct.Pair, ptr @pair, {{.*}}))
// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S"(ptr nonnull @var, ptr nonnull getelementptr inbounds ([2 x [2 x i32]], ptr @arr, {{.*}}), ptr nonnull @test_s)
void test_s(void) {
asm("// %0 %1 %2" :: "s"(&var), "s"(&arr[1][1]), "s"(test_s));
asm("// %0" :: "s"(&pair.b));

asm("// %0 %1 %2" :: "S"(&var), "S"(&arr[1][1]), "S"(test_s));
}
8 changes: 8 additions & 0 deletions clang/test/CodeGen/aarch64-inline-asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,11 @@ void test_reduced_gpr_constraints(int var32, long var64) {
// CHECK: [[ARG2:%.+]] = load i64, ptr
// CHECK: call void asm sideeffect "add x0, x0, $0", "@3Ucj,~{x0}"(i64 [[ARG2]])
}

void test_sme_constraints(){
asm("movt zt0[3, mul vl], z0" : : : "za");
// CHECK: call void asm sideeffect "movt zt0[3, mul vl], z0", "~{za}"()

asm("movt zt0[3, mul vl], z0" : : : "zt0");
// CHECK: call void asm sideeffect "movt zt0[3, mul vl], z0", "~{zt0}"()
}
18 changes: 9 additions & 9 deletions clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,20 +284,20 @@ int test_variadic_template() __arm_inout("za") {
// CHECK: attributes #[[SM_COMPATIBLE]] = { mustprogress noinline nounwind "aarch64_pstate_sm_compatible" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[SM_COMPATIBLE_DECL]] = { "aarch64_pstate_sm_compatible" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[SM_BODY]] = { mustprogress noinline nounwind "aarch64_pstate_sm_body" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_SHARED]] = { mustprogress noinline nounwind "aarch64_pstate_za_shared" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_SHARED_DECL]] = { "aarch64_pstate_za_shared" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_PRESERVED]] = { mustprogress noinline nounwind "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_PRESERVED_DECL]] = { "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_NEW]] = { mustprogress noinline nounwind "aarch64_pstate_za_new" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_SHARED]] = { mustprogress noinline nounwind "aarch64_inout_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_SHARED_DECL]] = { "aarch64_inout_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_PRESERVED]] = { mustprogress noinline nounwind "aarch64_preserves_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_PRESERVED_DECL]] = { "aarch64_preserves_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_NEW]] = { mustprogress noinline nounwind "aarch64_new_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[NORMAL_DEF]] = { mustprogress noinline nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[SM_ENABLED_CALL]] = { "aarch64_pstate_sm_enabled" }
// CHECK: attributes #[[SM_COMPATIBLE_CALL]] = { "aarch64_pstate_sm_compatible" }
// CHECK: attributes #[[SM_BODY_CALL]] = { "aarch64_pstate_sm_body" }
// CHECK: attributes #[[ZA_SHARED_CALL]] = { "aarch64_pstate_za_shared" }
// CHECK: attributes #[[ZA_PRESERVED_CALL]] = { "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" }
// CHECK: attributes #[[ZA_SHARED_CALL]] = { "aarch64_inout_za" }
// CHECK: attributes #[[ZA_PRESERVED_CALL]] = { "aarch64_preserves_za" }
// CHECK: attributes #[[NOUNWIND_CALL]] = { nounwind }
// CHECK: attributes #[[NOUNWIND_SM_ENABLED_CALL]] = { nounwind "aarch64_pstate_sm_enabled" }
// CHECK: attributes #[[NOUNWIND_SM_COMPATIBLE_CALL]] = { nounwind "aarch64_pstate_sm_compatible" }
// CHECK: attributes #[[NOUNWIND_ZA_SHARED_CALL]] = { nounwind "aarch64_pstate_za_shared" }
// CHECK: attributes #[[NOUNWIND_ZA_PRESERVED_CALL]] = { nounwind "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" }
// CHECK: attributes #[[NOUNWIND_ZA_SHARED_CALL]] = { nounwind "aarch64_inout_za" }
// CHECK: attributes #[[NOUNWIND_ZA_PRESERVED_CALL]] = { nounwind "aarch64_preserves_za" }

4 changes: 2 additions & 2 deletions clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_zero.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ void test_svzero_mask_za_2(void) __arm_inout("za") {
}

// CHECK-C-LABEL: define dso_local void @test_svzero_za(
// CHECK-C-SAME: ) local_unnamed_addr #[[ATTR0]] {
// CHECK-C-SAME: ) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// CHECK-C-NEXT: entry:
// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.zero(i32 255)
// CHECK-C-NEXT: ret void
//
// CHECK-CXX-LABEL: define dso_local void @_Z14test_svzero_zav(
// CHECK-CXX-SAME: ) local_unnamed_addr #[[ATTR0]] {
// CHECK-CXX-SAME: ) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// CHECK-CXX-NEXT: entry:
// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.zero(i32 255)
// CHECK-CXX-NEXT: ret void
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CodeGen/aarch64-targetattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,19 @@ void minusarch() {}
// CHECK: attributes #0 = { {{.*}} "target-features"="+crc,+fp-armv8,+lse,+neon,+ras,+rdm,+v8.1a,+v8.2a,+v8a" }
// CHECK: attributes #1 = { {{.*}} "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+v8.1a,+v8.2a,+v8a" }
// CHECK: attributes #2 = { {{.*}} "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8a" }
// CHECK: attributes #3 = { {{.*}} "target-features"="+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+ras,+rcpc,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" }
// CHECK: attributes #3 = { {{.*}} "target-features"="+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+ras,+rcpc,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" }
// CHECK: attributes #4 = { {{.*}} "target-cpu"="cortex-a710" "target-features"="+bf16,+complxnum,+crc,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+ras,+rcpc,+rdm,+sb,+sve,+sve2,+sve2-bitperm" }
// CHECK: attributes #5 = { {{.*}} "tune-cpu"="cortex-a710" }
// CHECK: attributes #6 = { {{.*}} "target-cpu"="generic" }
// CHECK: attributes #7 = { {{.*}} "tune-cpu"="generic" }
// CHECK: attributes #8 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs" "tune-cpu"="cortex-a710" }
// CHECK: attributes #9 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve" "tune-cpu"="cortex-a710" }
// CHECK: attributes #10 = { {{.*}} "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2" }
// CHECK: attributes #11 = { {{.*}} "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,-sve" }
// CHECK: attributes #10 = { {{.*}} "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2" }
// CHECK: attributes #11 = { {{.*}} "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,-sve" }
// CHECK: attributes #12 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
// CHECK: attributes #13 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve,-sve2" }
// CHECK: attributes #14 = { {{.*}} "target-features"="+fullfp16" }
// CHECK: attributes #15 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" }
// CHECK: attributes #16 = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="true" {{.*}} "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" }
// CHECK: attributes #15 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" }
// CHECK: attributes #16 = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="true" {{.*}} "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" }
// CHECK: attributes #17 = { {{.*}} "target-features"="-neon" }
// CHECK: attributes #18 = { {{.*}} "target-features"="-v9.3a" }
9 changes: 3 additions & 6 deletions clang/test/CodeGenOpenCL/builtins-amdgcn-wave32.cl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-unknown-unknown -D__AMDGCN_WAVEFRONT_SIZE=32 -target-feature +wavefrontsize32 -S -emit-llvm -o - %s | FileCheck -enable-var-scope %s
// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-unknown-unknown -target-cpu gfx1010 -S -emit-llvm -o - %s | FileCheck -enable-var-scope %s
// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-unknown-unknown -target-cpu gfx1010 -target-feature +wavefrontsize32 -S -emit-llvm -o - %s | FileCheck -enable-var-scope %s
Expand All @@ -24,23 +25,19 @@ void test_ballot_wave32_target_attr(global uint* out, int a, int b)
}

// CHECK-LABEL: @test_read_exec(
// CHECK: call i64 @llvm.amdgcn.ballot.i64(i1 true)
// CHECK: call i32 @llvm.amdgcn.ballot.i32(i1 true)
void test_read_exec(global uint* out) {
*out = __builtin_amdgcn_read_exec();
}

// CHECK: declare i64 @llvm.amdgcn.ballot.i64(i1) #[[$NOUNWIND_READONLY:[0-9]+]]

// CHECK-LABEL: @test_read_exec_lo(
// CHECK: call i32 @llvm.amdgcn.ballot.i32(i1 true)
void test_read_exec_lo(global uint* out) {
*out = __builtin_amdgcn_read_exec_lo();
}

// CHECK-LABEL: @test_read_exec_hi(
// CHECK: call i64 @llvm.amdgcn.ballot.i64(i1 true)
// CHECK: lshr i64 [[A:%.*]], 32
// CHECK: trunc i64 [[B:%.*]] to i32
// CHECK: store i32 0, ptr addrspace(1) %out
void test_read_exec_hi(global uint* out) {
*out = __builtin_amdgcn_read_exec_hi();
}
Expand Down
16 changes: 8 additions & 8 deletions clang/test/CodeGenOpenCL/builtins-amdgcn-wmma-w32-gfx10-err.cl
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ void test_amdgcn_wmma_f32_16x16x16_bf16_w32(global v8f* out8f, v16s a16s, v16s b
global v16s* out16s, v2i a2i, v2i b2i, v16s c16s,
global v8i* out8i, v4i a4i, v4i b4i, v8i c8i)
{
*out8f = __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a16h, b16h, c8f); // expected-error{{'__builtin_amdgcn_wmma_f32_16x16x16_f16_w32' needs target feature gfx11-insts}}
*out8f = __builtin_amdgcn_wmma_f32_16x16x16_bf16_w32(a16s, b16s, c8f); // expected-error{{'__builtin_amdgcn_wmma_f32_16x16x16_bf16_w32' needs target feature gfx11-insts}}
*out16h = __builtin_amdgcn_wmma_f16_16x16x16_f16_w32(a16h, b16h, c16h, true); // expected-error{{'__builtin_amdgcn_wmma_f16_16x16x16_f16_w32' needs target feature gfx11-insts}}
*out16s = __builtin_amdgcn_wmma_bf16_16x16x16_bf16_w32(a16s, b16s, c16s, true); // expected-error{{'__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w32' needs target feature gfx11-insts}}
*out16h = __builtin_amdgcn_wmma_f16_16x16x16_f16_tied_w32(a16h, b16h, c16h, true); // expected-error{{'__builtin_amdgcn_wmma_f16_16x16x16_f16_tied_w32' needs target feature gfx11-insts}}
*out16s = __builtin_amdgcn_wmma_bf16_16x16x16_bf16_tied_w32(a16s, b16s, c16s, true); // expected-error{{'__builtin_amdgcn_wmma_bf16_16x16x16_bf16_tied_w32' needs target feature gfx11-insts}}
*out8i = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32(true, a4i, true, b4i, c8i, false); // expected-error{{'__builtin_amdgcn_wmma_i32_16x16x16_iu8_w32' needs target feature gfx11-insts}}
*out8i = __builtin_amdgcn_wmma_i32_16x16x16_iu4_w32(true, a2i, true, b2i, c8i, false); // expected-error{{'__builtin_amdgcn_wmma_i32_16x16x16_iu4_w32' needs target feature gfx11-insts}}
*out8f = __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a16h, b16h, c8f); // expected-error{{'__builtin_amdgcn_wmma_f32_16x16x16_f16_w32' needs target feature gfx11-insts,wavefrontsize32}}
*out8f = __builtin_amdgcn_wmma_f32_16x16x16_bf16_w32(a16s, b16s, c8f); // expected-error{{'__builtin_amdgcn_wmma_f32_16x16x16_bf16_w32' needs target feature gfx11-insts,wavefrontsize32}}
*out16h = __builtin_amdgcn_wmma_f16_16x16x16_f16_w32(a16h, b16h, c16h, true); // expected-error{{'__builtin_amdgcn_wmma_f16_16x16x16_f16_w32' needs target feature gfx11-insts,wavefrontsize32}}
*out16s = __builtin_amdgcn_wmma_bf16_16x16x16_bf16_w32(a16s, b16s, c16s, true); // expected-error{{'__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w32' needs target feature gfx11-insts,wavefrontsize32}}
*out16h = __builtin_amdgcn_wmma_f16_16x16x16_f16_tied_w32(a16h, b16h, c16h, true); // expected-error{{'__builtin_amdgcn_wmma_f16_16x16x16_f16_tied_w32' needs target feature gfx11-insts,wavefrontsize32}}
*out16s = __builtin_amdgcn_wmma_bf16_16x16x16_bf16_tied_w32(a16s, b16s, c16s, true); // expected-error{{'__builtin_amdgcn_wmma_bf16_16x16x16_bf16_tied_w32' needs target feature gfx11-insts,wavefrontsize32}}
*out8i = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32(true, a4i, true, b4i, c8i, false); // expected-error{{'__builtin_amdgcn_wmma_i32_16x16x16_iu8_w32' needs target feature gfx11-insts,wavefrontsize32}}
*out8i = __builtin_amdgcn_wmma_i32_16x16x16_iu4_w32(true, a2i, true, b2i, c8i, false); // expected-error{{'__builtin_amdgcn_wmma_i32_16x16x16_iu4_w32' needs target feature gfx11-insts,wavefrontsize32}}
}

#endif
18 changes: 9 additions & 9 deletions clang/test/CodeGenOpenCL/builtins-amdgcn-wmma-w64-gfx10-err.cl
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ void test_amdgcn_wmma_f32_16x16x16_bf16_w64(global v4f* out4f, v16h a16h, v16h b
global v8s* out8s, v4i a4i, v4i b4i, v8s c8s,
global v4i* out4i, v2i a2i, v2i b2i, v4i c4i)
{
*out4f = __builtin_amdgcn_wmma_f32_16x16x16_f16_w64(a16h, b16h, c4f); // expected-error{{'__builtin_amdgcn_wmma_f32_16x16x16_f16_w64' needs target feature gfx11-insts}}
*out4f = __builtin_amdgcn_wmma_f32_16x16x16_bf16_w64(a16s, b16s, c4f); // expected-error{{'__builtin_amdgcn_wmma_f32_16x16x16_bf16_w64' needs target feature gfx11-insts}}
*out8h = __builtin_amdgcn_wmma_f16_16x16x16_f16_w64(a16h, b16h, c8h, true); // expected-error{{'__builtin_amdgcn_wmma_f16_16x16x16_f16_w64' needs target feature gfx11-insts}}
*out8s = __builtin_amdgcn_wmma_bf16_16x16x16_bf16_w64(a16s, b16s, c8s, true); // expected-error{{'__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w64' needs target feature gfx11-insts}}
*out8h = __builtin_amdgcn_wmma_f16_16x16x16_f16_tied_w64(a16h, b16h, c8h, true); // expected-error{{'__builtin_amdgcn_wmma_f16_16x16x16_f16_tied_w64' needs target feature gfx11-insts}}
*out8s = __builtin_amdgcn_wmma_bf16_16x16x16_bf16_tied_w64(a16s, b16s, c8s, true); // expected-error{{'__builtin_amdgcn_wmma_bf16_16x16x16_bf16_tied_w64' needs target feature gfx11-insts}}
*out4i = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w64(true, a4i, true, b4i, c4i, false); // expected-error{{'__builtin_amdgcn_wmma_i32_16x16x16_iu8_w64' needs target feature gfx11-insts}}
*out4i = __builtin_amdgcn_wmma_i32_16x16x16_iu4_w64(true, a2i, true, b2i, c4i, false); // expected-error{{'__builtin_amdgcn_wmma_i32_16x16x16_iu4_w64' needs target feature gfx11-insts}}
*out4f = __builtin_amdgcn_wmma_f32_16x16x16_f16_w64(a16h, b16h, c4f); // expected-error{{'__builtin_amdgcn_wmma_f32_16x16x16_f16_w64' needs target feature gfx11-insts,wavefrontsize64}}
*out4f = __builtin_amdgcn_wmma_f32_16x16x16_bf16_w64(a16s, b16s, c4f); // expected-error{{'__builtin_amdgcn_wmma_f32_16x16x16_bf16_w64' needs target feature gfx11-insts,wavefrontsize64}}
*out8h = __builtin_amdgcn_wmma_f16_16x16x16_f16_w64(a16h, b16h, c8h, true); // expected-error{{'__builtin_amdgcn_wmma_f16_16x16x16_f16_w64' needs target feature gfx11-insts,wavefrontsize64}}
*out8s = __builtin_amdgcn_wmma_bf16_16x16x16_bf16_w64(a16s, b16s, c8s, true); // expected-error{{'__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w64' needs target feature gfx11-insts,wavefrontsize64}}
*out8h = __builtin_amdgcn_wmma_f16_16x16x16_f16_tied_w64(a16h, b16h, c8h, true); // expected-error{{'__builtin_amdgcn_wmma_f16_16x16x16_f16_tied_w64' needs target feature gfx11-insts,wavefrontsize64}}
*out8s = __builtin_amdgcn_wmma_bf16_16x16x16_bf16_tied_w64(a16s, b16s, c8s, true); // expected-error{{'__builtin_amdgcn_wmma_bf16_16x16x16_bf16_tied_w64' needs target feature gfx11-insts,wavefrontsize64}}
*out4i = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w64(true, a4i, true, b4i, c4i, false); // expected-error{{'__builtin_amdgcn_wmma_i32_16x16x16_iu8_w64' needs target feature gfx11-insts,wavefrontsize64}}
*out4i = __builtin_amdgcn_wmma_i32_16x16x16_iu4_w64(true, a2i, true, b2i, c4i, false); // expected-error{{'__builtin_amdgcn_wmma_i32_16x16x16_iu4_w64' needs target feature gfx11-insts,wavefrontsize64}}
}

#endif
#endif
2 changes: 1 addition & 1 deletion clang/test/CodeGenOpenCL/builtins-amdgcn-wmma-w64.cl
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
// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1100 -DWMMA_GFX1100_TESTS -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX1100
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1100 -target-feature +wavefrontsize64 -DWMMA_GFX1100_TESTS -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX1100

typedef float v4f __attribute__((ext_vector_type(4)));
typedef half v8h __attribute__((ext_vector_type(8)));
Expand Down
29 changes: 29 additions & 0 deletions clang/test/CoverageMapping/if.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,35 @@ constexpr int check_macro_consteval_if_skipped(int i) { // CHECK-NEXT: [[@LINE
return i;
}

struct false_value {
constexpr operator bool() {
return false;
}
};

template <typename> struct dependable_false_value {
constexpr operator bool() {
return false;
}
};

// GH-80285
void should_not_crash() {
if constexpr (false_value{}) { };
}

template <typename> void should_not_crash_dependable() {
if constexpr (dependable_false_value<int>{}) { };
}

void should_not_crash_with_template_instance() {
should_not_crash_dependable<int>();
}

void should_not_crash_with_requires_expr() {
if constexpr (requires {42;}) { };
}

int instantiate_consteval(int i) {
i *= check_consteval_with_else_discarded_then(i);
i *= check_notconsteval_with_else_discarded_else(i);
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Driver/amdgpu-openmp-toolchain.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,7 @@
// RUN: %clang -### -target x86_64-pc-linux-gnu -fopenmp --offload-arch=gfx90a \
// RUN: -O3 -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-OPT
// CHECK-OPT: clang-linker-wrapper{{.*}}"--opt-level=O3"

// RUN: %clang -### --target=x86_64-unknown-linux-gnu -emit-llvm -S -fopenmp -fopenmp-targets=amdgcn-amd-amdhsa -Xopenmp-target=amdgcn-amd-amdhsa -march=gfx803 -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-WARN-ATOMIC
// CHECK-WARN-ATOMIC-NOT: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-Werror=atomic-alignment"
// CHECK-WARN-ATOMIC: "-cc1" "-triple" "amdgcn-amd-amdhsa"{{.*}}"-Werror=atomic-alignment"
3 changes: 3 additions & 0 deletions clang/test/Driver/amdgpu-toolchain-opencl.cl
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@
// RUN: %clang -### --target=amdgcn-amd-amdhsa-opencl -Wl,--unresolved-symbols=ignore-all -x cl -mcpu=fiji -nogpulib %s 2>&1 | FileCheck -check-prefix=CHK-LINK_UR %s
// RUN: %clang -### --target=amdgcn-amd-amdhsa-opencl -Xlinker --unresolved-symbols=ignore-all -x cl -mcpu=fiji -nogpulib %s 2>&1 | FileCheck -check-prefix=CHK-LINK_UR %s
// CHK-LINK_UR: ld.lld{{.*}} "--no-undefined"{{.*}} "--unresolved-symbols=ignore-all"

// RUN: %clang -### --target=amdgcn-amd-amdhsa-opencl -x cl -c -emit-llvm -mcpu=fiji -nogpulib %s 2>&1 | FileCheck -check-prefix=CHECK-WARN-ATOMIC %s
// CHECK-WARN-ATOMIC: "-cc1"{{.*}} "-Werror=atomic-alignment"
8 changes: 8 additions & 0 deletions clang/test/Driver/basic-block-address-map.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %clang -### -target x86_64 -fbasic-block-address-map %s -S 2>&1 | FileCheck -check-prefix=CHECK-PRESENT %s
// CHECK-PRESENT: -fbasic-block-address-map

// RUN: %clang -### -target x86_64 -fno-basic-block-address-map %s -S 2>&1 | FileCheck %s --check-prefix=CHECK-ABSENT
// CHECK-ABSENT-NOT: -fbasic-block-address-map

// RUN: not %clang -c -target x86_64-apple-darwin10 -fbasic-block-address-map %s -S 2>&1 | FileCheck -check-prefix=CHECK-TRIPLE %s
// CHECK-TRIPLE: error: unsupported option '-fbasic-block-address-map' for target
16 changes: 16 additions & 0 deletions clang/test/Driver/hip-options.hip
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,19 @@

// RUN: %clang -fdriver-only -c -Werror --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib -fno-offload-uniform-block \
// RUN: -foffload-uniform-block --cuda-gpu-arch=gfx906 %s 2>&1 | count 0

// Check -Werror=atomic-alignment is passed for amdpu by default.

// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib \
// RUN: --cuda-gpu-arch=gfx906 %s 2>&1 | FileCheck -check-prefix=WARN-ATOMIC %s
// WARN-ATOMIC: clang{{.*}} "-triple" "amdgcn-amd-amdhsa" {{.*}} "-Werror=atomic-alignment"
// WARN-ATOMIC-NOT: clang{{.*}} "-triple" "x86_64-unknown-linux-gnu" {{.*}} "-Werror=atomic-alignment"

// Check the default -Werror=atomic-alignment can be overridden.

// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib \
// RUN: --cuda-gpu-arch=gfx906 -Xarch_device -Wno-error=atomic-alignment %s \
// RUN: 2>&1 | FileCheck -check-prefix=NO-WARN-ATOMIC %s
// NO-WARN-ATOMIC: clang{{.*}} "-triple" "amdgcn-amd-amdhsa" {{.*}} "-Werror=atomic-alignment" {{.*}} "-Wno-error=atomic-alignment"
// NO-WARN-ATOMIC-NOT: clang{{.*}} "-triple" "x86_64-unknown-linux-gnu" {{.*}} "-Werror=atomic-alignment"
// NO-WARN-ATOMIC-NOT: clang{{.*}} "-triple" "x86_64-unknown-linux-gnu" {{.*}} "-Wno-error=atomic-alignment"
17 changes: 16 additions & 1 deletion clang/test/Driver/rocm-detect.hip
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,18 @@
// RUN: --hip-path=%t/myhip --print-rocm-search-dirs %s 2>&1 \
// RUN: | FileCheck -check-prefixes=ROCM-ENV,HIP-PATH %s

// Test detecting /usr directory.
// RUN: rm -rf %t/*
// RUN: cp -r %S/Inputs/rocm %t/usr
// RUN: mkdir -p %t/usr/share/hip
// RUN: mv %t/usr/bin/.hipVersion %t/usr/share/hip/version
// RUN: mkdir -p %t/usr/local
// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=gfx1010 --sysroot=%t \
// RUN: --print-rocm-search-dirs --hip-link %s 2>&1 \
// RUN: | FileCheck -check-prefixes=USR %s

// Test detecting latest /opt/rocm-{release} directory.
// RUN: rm -rf %t/opt
// RUN: rm -rf %t/*
// RUN: mkdir -p %t/opt
// RUN: cp -r %S/Inputs/rocm %t/opt/rocm-3.9.0-1234
// RUN: cp -r %S/Inputs/rocm %t/opt/rocm-3.10.0
Expand Down Expand Up @@ -130,6 +140,11 @@
// ROCM-PATH: "-idirafter" "[[ROCM_PATH]]/include"
// ROCM-PATH: "-L[[ROCM_PATH]]/lib" {{.*}}"-lamdhip64"

// USR: ROCm installation search path: [[ROCM_PATH:.*/usr$]]
// USR: "-mlink-builtin-bitcode" "[[ROCM_PATH]]/amdgcn/bitcode/oclc_isa_version_1010.bc"
// USR: "-idirafter" "[[ROCM_PATH]]/include"
// USR: "-L[[ROCM_PATH]]/lib" {{.*}}"-lamdhip64"

// ROCM-REL: ROCm installation search path: {{.*}}/opt/rocm
// ROCM-REL: ROCm installation search path: {{.*}}/opt/rocm-3.10.0

Expand Down
2 changes: 1 addition & 1 deletion clang/test/Interpreter/cxx20-modules.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// RUN: %clang -std=c++20 %t/mod.cppm --precompile \
// RUN: -o %t/mod.pcm --target=x86_64-linux-gnu
// RUN: %clang -fPIC %t/mod.pcm -c -o %t/mod.o --target=x86_64-linux-gnu
// RUN: %clang -fPIC -shared %t/mod.o -o %t/libmod.so --target=x86_64-linux-gnu
// RUN: %clang -nostdlib -fPIC -shared %t/mod.o -o %t/libmod.so --target=x86_64-linux-gnu
//
// RUN: cat %t/import.cpp | env LD_LIBRARY_PATH=%t:$LD_LIBRARY_PATH \
// RUN: clang-repl -Xcc=-std=c++20 -Xcc=-fmodule-file=M=%t/mod.pcm \
Expand Down
10 changes: 5 additions & 5 deletions clang/test/Modules/aarch64-sme-keywords.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ import A;
//
// CHECK:declare void @_ZW1A22f_streaming_compatiblev() #[[STREAMING_COMPATIBLE_DECL:[0-9]+]]
//
// CHECK-DAG: attributes #[[SHARED_ZA_DEF]] = {{{.*}} "aarch64_pstate_za_shared" {{.*}}}
// CHECK-DAG: attributes #[[SHARED_ZA_DECL]] = {{{.*}} "aarch64_pstate_za_shared" {{.*}}}
// CHECK-DAG: attributes #[[PRESERVES_ZA_DECL]] = {{{.*}} "aarch64_pstate_za_preserved" {{.*}}}
// CHECK-DAG: attributes #[[SHARED_ZA_DEF]] = {{{.*}} "aarch64_inout_za" {{.*}}}
// CHECK-DAG: attributes #[[SHARED_ZA_DECL]] = {{{.*}} "aarch64_inout_za" {{.*}}}
// CHECK-DAG: attributes #[[PRESERVES_ZA_DECL]] = {{{.*}} "aarch64_preserves_za" {{.*}}}
// CHECK-DAG: attributes #[[NORMAL_DEF]] = {{{.*}}}
// CHECK-DAG: attributes #[[STREAMING_DECL]] = {{{.*}} "aarch64_pstate_sm_enabled" {{.*}}}
// CHECK-DAG: attributes #[[STREAMING_COMPATIBLE_DECL]] = {{{.*}} "aarch64_pstate_sm_compatible" {{.*}}}
// CHECK-DAG: attributes #[[SHARED_ZA_USE]] = { "aarch64_pstate_za_shared" }
// CHECK-DAG: attributes #[[PRESERVES_ZA_USE]] = { "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" }
// CHECK-DAG: attributes #[[SHARED_ZA_USE]] = { "aarch64_inout_za" }
// CHECK-DAG: attributes #[[PRESERVES_ZA_USE]] = { "aarch64_preserves_za" }
// CHECK-DAG: attributes #[[STREAMING_USE]] = { "aarch64_pstate_sm_enabled" }
// CHECK-DAG: attributes #[[STREAMING_COMPATIBLE_USE]] = { "aarch64_pstate_sm_compatible" }

Expand Down
3 changes: 1 addition & 2 deletions clang/test/OpenMP/declare_simd_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ int main();
int main();

struct A {
// expected-error@+1 {{function declaration is expected after 'declare simd' directive}}
#pragma omp declare simd
template<typename T>
T infunc1(T a), infunc2(T a);
T infunc1(T a);
};

// expected-error@+1 {{single declaration is expected after 'declare simd' directive}}
Expand Down
79 changes: 65 additions & 14 deletions clang/test/Preprocessor/aarch64-target-features.c

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions clang/test/Preprocessor/has_builtin_cpuid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %clang_cc1 -fsyntax-only -triple arm64-- -DARM -verify %s
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-- -DX86 -verify %s
// RUN: %clang_cc1 -fsyntax-only -triple powerpc64-unknown-linux-gnu -DPPC \
// RUN: -verify %s
// expected-no-diagnostics
#if __has_builtin(__builtin_cpu_is)
# ifdef ARM
# error "ARM shouldn't have __builtin_cpu_is"
# endif
#endif
#if __has_builtin(__builtin_cpu_init)
# if defined(ARM) || defined(PPC)
# error "ARM/PPC shouldn't have __builtin_cpu_init"
# endif
#endif
#if __has_builtin(__builtin_cpu_supports)
# ifdef ARM
# error "ARM shouldn't have __builtin_cpu_supports"
# endif
#endif
2 changes: 2 additions & 0 deletions clang/test/Preprocessor/init-aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
// AARCH64-NEXT: #define __ARM_PCS_AAPCS64 1
// AARCH64-NEXT: #define __ARM_SIZEOF_MINIMAL_ENUM 4
// AARCH64-NEXT: #define __ARM_SIZEOF_WCHAR_T 4
// AARCH64-NEXT: #define __ARM_STATE_ZA 1
// AARCH64-NEXT: #define __ARM_STATE_ZT0 1
// AARCH64-NEXT: #define __ATOMIC_ACQUIRE 2
// AARCH64-NEXT: #define __ATOMIC_ACQ_REL 4
// AARCH64-NEXT: #define __ATOMIC_CONSUME 1
Expand Down
164 changes: 163 additions & 1 deletion clang/test/Preprocessor/riscv-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,26 @@
// CHECK-NOT: __riscv_m {{.*$}}
// CHECK-NOT: __riscv_mul {{.*$}}
// CHECK-NOT: __riscv_muldiv {{.*$}}
// CHECK-NOT: __riscv_shcounterenw {{.*$}}
// CHECK-NOT: __riscv_shgatpa {{.*$}}
// CHECK-NOT: __riscv_shtvala {{.*$}}
// CHECK-NOT: __riscv_shvsatpa {{.*$}}
// CHECK-NOT: __riscv_shvstvala {{.*$}}
// CHECK-NOT: __riscv_shvstvecd {{.*$}}
// CHECK-NOT: __riscv_smaia {{.*$}}
// CHECK-NOT: __riscv_ssaia {{.*$}}
// CHECK-NOT: __riscv_smepmp {{.*$}}
// CHECK-NOT: __riscv_ssaia {{.*$}}
// CHECK-NOT: __riscv_ssccptr {{.*$}}
// CHECK-NOT: __riscv_sscounterenw {{.*$}}
// CHECK-NOT: __riscv_ssstateen {{.*$}}
// CHECK-NOT: __riscv_ssstrict {{.*$}}
// CHECK-NOT: __riscv_sstc {{.*$}}
// CHECK-NOT: __riscv_sstvala {{.*$}}
// CHECK-NOT: __riscv_sstvecd {{.*$}}
// CHECK-NOT: __riscv_ssu64xl {{.*$}}
// CHECK-NOT: __riscv_svade {{.*$}}
// CHECK-NOT: __riscv_svadu {{.*$}}
// CHECK-NOT: __riscv_svbare {{.*$}}
// CHECK-NOT: __riscv_svinval {{.*$}}
// CHECK-NOT: __riscv_svnapot {{.*$}}
// CHECK-NOT: __riscv_svpbmt {{.*$}}
Expand Down Expand Up @@ -144,6 +161,7 @@

// CHECK-NOT: __riscv_zaamo {{.*$}}
// CHECK-NOT: __riscv_zacas {{.*$}}
// CHECK-NOT: __riscv_zalasr {{.*$}}
// CHECK-NOT: __riscv_zalrsc {{.*$}}
// CHECK-NOT: __riscv_zcmop {{.*$}}
// CHECK-NOT: __riscv_zfbfmin {{.*$}}
Expand Down Expand Up @@ -271,6 +289,142 @@
// CHECK-M-EXT: __riscv_mul 1
// CHECK-M-EXT: __riscv_muldiv 1

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32ishcounterenw -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHCOUNTERENW-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64ishcounterenw -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHCOUNTERENW-EXT %s
// CHECK-SHCOUNTERENW-EXT: __riscv_shcounterenw 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32ishgatpa -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHGATPA-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64ishgatpa -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHGATPA-EXT %s
// CHECK-SHGATPA-EXT: __riscv_shgatpa 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32ishtvala -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHTVALA-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64ishtvala -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHTVALA-EXT %s
// CHECK-SHTVALA-EXT: __riscv_shtvala 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32ishvsatpa -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHVSATPA-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64ishvsatpa -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHVSATPA-EXT %s
// CHECK-SHVSATPA-EXT: __riscv_shvsatpa 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32ishvstvala -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHVSTVALA-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64ishvstvala -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHVSTVALA-EXT %s
// CHECK-SHVSTVALA-EXT: __riscv_shvstvala 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32ishvstvecd -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHVSTVECD-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64ishvstvecd -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SHVSTVECD-EXT %s
// CHECK-SHVSTVECD-EXT: __riscv_shvstvecd 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32issccptr -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCCPTR-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64issccptr -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCCPTR-EXT %s
// CHECK-SSCCPTR-EXT: __riscv_ssccptr 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32isscounterenw -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCOUNTERENW-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64isscounterenw -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCOUNTERENW-EXT %s
// CHECK-SSCOUNTERENW-EXT: __riscv_sscounterenw 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32issstateen -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSSTATEEN-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64issstateen -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSSTATEEN-EXT %s
// CHECK-SSSTATEEN-EXT: __riscv_ssstateen 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32issstrict -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSSTRICT-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64issstrict -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSSTRICT-EXT %s
// CHECK-SSSTRICT-EXT: __riscv_ssstrict 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32isstc -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSTC-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64isstc -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSTC-EXT %s
// CHECK-SSTC-EXT: __riscv_sstc 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32isstvala -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSTVALA-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64isstvala -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSTVALA-EXT %s
// CHECK-SSTVALA-EXT: __riscv_sstvala 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32isstvecd -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSTVECD-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64isstvecd -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSTVECD-EXT %s
// CHECK-SSTVECD-EXT: __riscv_sstvecd 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32issu64xl -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSU64XL-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64issu64xl -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSU64XL-EXT %s
// CHECK-SSU64XL-EXT: __riscv_ssu64xl 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32isvade -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SVADE-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64isvade -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SVADE-EXT %s
// CHECK-SVADE-EXT: __riscv_svade 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32isvadu -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SVADU-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64isvadu -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SVADU-EXT %s
// CHECK-SVADU-EXT: __riscv_svadu 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32isvbare -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SVBARE-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64isvbare -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SVBARE-EXT %s
// CHECK-SVBARE-EXT: __riscv_svbare 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32isvinval -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SVINVAL-EXT %s
Expand Down Expand Up @@ -1333,6 +1487,14 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
// CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}}

// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zalasr0p1 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_zalasr0p1 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s
// CHECK-ZALASR-EXT: __riscv_zalasr 1000{{$}}

// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zalrsc0p2 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZALRSC-EXT %s
Expand Down
1 change: 1 addition & 0 deletions clang/test/Sema/PR2919-builtin-types-compat-strips-crv.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only %s
// RUN: %clang_cc1 -fsyntax-only %s -fexperimental-new-constant-interpreter

typedef struct foo T0;
typedef const struct foo T1;
Expand Down
13 changes: 11 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 +sme -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify=expected-cpp -x c++ %s
// 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

// Valid attributes

Expand Down Expand Up @@ -445,3 +445,12 @@ void conflicting_state_attrs_preserves_out_zt0(void) __arm_preserves("zt0") __ar
// expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
// expected-error@+1 {{conflicting attributes for state 'zt0'}}
void conflicting_state_attrs_preserves_inout_zt0(void) __arm_preserves("zt0") __arm_inout("zt0");

// Test that we get a diagnostic for unimplemented case.
void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0")) __arm_inout("za", "zt0") {
// expected-cpp-error@+4 {{call to a function that shares state other than 'za' from a function that has live 'za' state requires a spill/fill of ZA, which is not yet implemented}}
// expected-cpp-note@+3 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
// expected-error@+2 {{call to a function that shares state other than 'za' from a function that has live 'za' state requires a spill/fill of ZA, which is not yet implemented}}
// expected-note@+1 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
share_zt0_only();
}
1 change: 1 addition & 0 deletions clang/test/Sema/auto-type.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -fsyntax-only -Wno-strict-prototypes -verify -pedantic -std=c11
// RUN: %clang_cc1 %s -fsyntax-only -Wno-strict-prototypes -verify -pedantic -std=c11 -fexperimental-new-constant-interpreter

__auto_type a = 5; // expected-warning {{'__auto_type' is a GNU extension}}
__extension__ __auto_type a1 = 5;
Expand Down
1 change: 1 addition & 0 deletions clang/test/Sema/c2x-auto.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c2x -verify -pedantic -Wno-comments %s
// RUN: %clang_cc1 -std=c2x -verify -pedantic -Wno-comments %s -fexperimental-new-constant-interpreter

void test_basic_types(void) {
auto undefined; // expected-error {{declaration of variable 'undefined' with deduced type 'auto' requires an initializer}}
Expand Down
1 change: 1 addition & 0 deletions clang/test/Sema/c2x-bool.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify %s
// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify %s -fexperimental-new-constant-interpreter

_Static_assert(_Generic(true, _Bool : 1, default: 0));
_Static_assert(_Generic(false, _Bool : 1, default: 0));
Expand Down
1 change: 1 addition & 0 deletions clang/test/Sema/check-increment.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter
// expected-no-diagnostics

int printf(const char *, ...);
Expand Down
8 changes: 8 additions & 0 deletions clang/test/Sema/inline-asm-validate-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ void K(int k) {
asm volatile ("" :: "K"(AboveMax)); // expected-error{{value '32' out of range for constraint 'K'}}
}

void test_s(int i) {
asm("" :: "s"(test_s(0))); // expected-error{{invalid type 'void' in asm input for constraint 's'}}
/// Codegen error
asm("" :: "s"(i));

asm("" :: "S"(test_s(0))); // expected-error{{invalid type 'void' in asm input for constraint 'S'}}
}

void test_clobber_conflict(void) {
register long x10 asm("x10");
asm volatile("" :: "r"(x10) : "x10"); // expected-error {{conflicts with asm clobber list}}
Expand Down
3 changes: 2 additions & 1 deletion clang/test/Sema/warn-cast-qual.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -Wcast-qual -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -x c++ -fsyntax-only -Wcast-qual -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -Wcast-qual -verify %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -x c++ -fsyntax-only -Wcast-qual -verify %s -fexperimental-new-constant-interpreter

#include <stdint.h>

Expand Down
8 changes: 8 additions & 0 deletions clang/test/SemaCXX/datasizeof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,11 @@ struct S {
};

static_assert(S{}.i == 9);

namespace GH80284 {
struct Bar; // expected-note{{forward declaration}}
struct Foo {
Bar x; // expected-error{{field has incomplete type}}
};
constexpr int a = __datasizeof(Foo);
}
29 changes: 24 additions & 5 deletions clang/test/SemaCXX/decomposition-openmp.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@

// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 -fopenmp %s

// FIXME: OpenMP should support capturing structured bindings
// Okay, not an OpenMP capture.
auto f() {
int i[2] = {};
auto [a, b] = i; // expected-note 2{{declared here}}
auto [a, b] = i;
return [=, &a] {
// expected-error@-1 {{capturing a structured binding is not yet supported in OpenMP}}
return a + b;
// expected-error@-1 {{capturing a structured binding is not yet supported in OpenMP}}
};
}

// Okay, not an OpenMP capture.
void foo(int);
void g() {
#pragma omp parallel
{
int i[2] = {};
auto [a, b] = i;
auto L = [&] { foo(a+b); };
}
}

// FIXME: OpenMP should support capturing structured bindings
void h() {
int i[2] = {};
auto [a, b] = i; // expected-note 2{{declared here}}
#pragma omp parallel
{
// expected-error@+1 2{{capturing a structured binding is not yet supported in OpenMP}}
foo(a + b);
}
}
6 changes: 6 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2644,6 +2644,12 @@ TEST_F(TokenAnnotatorTest, StreamOperator) {
EXPECT_TRUE(Tokens[5]->MustBreakBefore);
}

TEST_F(TokenAnnotatorTest, UnderstandsElaboratedTypeSpecifier) {
auto Tokens = annotate("auto foo() -> enum En {}");
ASSERT_EQ(Tokens.size(), 10u) << Tokens;
EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_FunctionLBrace);
}

} // namespace
} // namespace format
} // namespace clang
3 changes: 2 additions & 1 deletion flang/include/flang/Lower/AbstractConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class CharBlock;
}
namespace semantics {
class Symbol;
class Scope;
class DerivedTypeSpec;
} // namespace semantics

Expand All @@ -59,7 +60,7 @@ struct Variable;
using SomeExpr = Fortran::evaluate::Expr<Fortran::evaluate::SomeType>;
using SymbolRef = Fortran::common::Reference<const Fortran::semantics::Symbol>;
using TypeConstructionStack =
llvm::SmallVector<std::pair<const Fortran::lower::SymbolRef, mlir::Type>>;
llvm::DenseMap<const Fortran::semantics::Scope *, mlir::Type>;
class StatementContext;

using ExprToValueMap = llvm::DenseMap<const SomeExpr *, mlir::Value>;
Expand Down
11 changes: 0 additions & 11 deletions flang/include/flang/Tools/CrossToolHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,6 @@ void setOffloadModuleInterfaceAttributes(
}
}

// Shares assinging of the OpenMP OffloadModuleInterface and its TargetCPU
// attribute accross Flang tools (bbc/flang)
void setOffloadModuleInterfaceTargetAttribute(mlir::ModuleOp &module,
llvm::StringRef targetCPU, llvm::StringRef targetFeatures) {
// Should be registered by the OpenMPDialect
if (auto offloadMod = llvm::dyn_cast<mlir::omp::OffloadModuleInterface>(
module.getOperation())) {
offloadMod.setTarget(targetCPU, targetFeatures);
}
}

void setOpenMPVersionAttribute(mlir::ModuleOp &module, int64_t version) {
module.getOperation()->setAttr(
mlir::StringAttr::get(module.getContext(), llvm::Twine{"omp.version"}),
Expand Down
3 changes: 0 additions & 3 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,6 @@ bool CodeGenAction::beginSourceFileAction() {
Fortran::common::LanguageFeature::OpenMP)) {
setOffloadModuleInterfaceAttributes(*mlirModule,
ci.getInvocation().getLangOpts());
setOffloadModuleInterfaceTargetAttribute(
*mlirModule, targetMachine.getTargetCPU(),
targetMachine.getTargetFeatureString());
setOpenMPVersionAttribute(*mlirModule,
ci.getInvocation().getLangOpts().OpenMPVersion);
}
Expand Down
68 changes: 41 additions & 27 deletions flang/lib/Lower/ConvertCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -912,37 +912,16 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
// element if this is an array in an elemental call.
hlfir::Entity actual = preparedActual.getActual(loc, builder);

// Handle the procedure pointer actual arguments.
if (actual.isProcedurePointer()) {
// Procedure pointer actual to procedure pointer dummy.
if (fir::isBoxProcAddressType(dummyType))
return PreparedDummyArgument{actual, /*cleanups=*/{}};
// Handle procedure arguments (procedure pointers should go through
// prepareProcedurePointerActualArgument).
if (hlfir::isFortranProcedureValue(dummyType)) {
// Procedure pointer actual to procedure dummy.
if (hlfir::isFortranProcedureValue(dummyType)) {
if (actual.isProcedurePointer()) {
actual = hlfir::derefPointersAndAllocatables(loc, builder, actual);
return PreparedDummyArgument{actual, /*cleanups=*/{}};
}
}

// NULL() actual to procedure pointer dummy
if (Fortran::evaluate::IsNullProcedurePointer(expr) &&
fir::isBoxProcAddressType(dummyType)) {
auto boxTy{Fortran::lower::getUntypedBoxProcType(builder.getContext())};
auto tempBoxProc{builder.createTemporary(loc, boxTy)};
hlfir::Entity nullBoxProc(
fir::factory::createNullBoxProc(builder, loc, boxTy));
builder.create<fir::StoreOp>(loc, nullBoxProc, tempBoxProc);
return PreparedDummyArgument{tempBoxProc, /*cleanups=*/{}};
}

if (actual.isProcedure()) {
// Procedure actual to procedure pointer dummy.
if (fir::isBoxProcAddressType(dummyType)) {
auto tempBoxProc{builder.createTemporary(loc, actual.getType())};
builder.create<fir::StoreOp>(loc, actual, tempBoxProc);
return PreparedDummyArgument{tempBoxProc, /*cleanups=*/{}};
}
// Procedure actual to procedure dummy.
assert(actual.isProcedure());
// Do nothing if this is a procedure argument. It is already a
// fir.boxproc/fir.tuple<fir.boxproc, len> as it should.
if (actual.getType() != dummyType)
Expand Down Expand Up @@ -1219,6 +1198,34 @@ static PreparedDummyArgument prepareUserCallActualArgument(
return result;
}

/// Prepare actual argument for a procedure pointer dummy.
static PreparedDummyArgument prepareProcedurePointerActualArgument(
mlir::Location loc, fir::FirOpBuilder &builder,
const Fortran::lower::PreparedActualArgument &preparedActual,
mlir::Type dummyType,
const Fortran::lower::CallerInterface::PassedEntity &arg,
const Fortran::lower::SomeExpr &expr, CallContext &callContext) {

// NULL() actual to procedure pointer dummy
if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(expr) &&
fir::isBoxProcAddressType(dummyType)) {
auto boxTy{Fortran::lower::getUntypedBoxProcType(builder.getContext())};
auto tempBoxProc{builder.createTemporary(loc, boxTy)};
hlfir::Entity nullBoxProc(
fir::factory::createNullBoxProc(builder, loc, boxTy));
builder.create<fir::StoreOp>(loc, nullBoxProc, tempBoxProc);
return PreparedDummyArgument{tempBoxProc, /*cleanups=*/{}};
}
hlfir::Entity actual = preparedActual.getActual(loc, builder);
if (actual.isProcedurePointer())
return PreparedDummyArgument{actual, /*cleanups=*/{}};
assert(actual.isProcedure());
// Procedure actual to procedure pointer dummy.
auto tempBoxProc{builder.createTemporary(loc, actual.getType())};
builder.create<fir::StoreOp>(loc, actual, tempBoxProc);
return PreparedDummyArgument{tempBoxProc, /*cleanups=*/{}};
}

/// Lower calls to user procedures with actual arguments that have been
/// pre-lowered but not yet prepared according to the interface.
/// This can be called for elemental procedures, but only with scalar
Expand Down Expand Up @@ -1284,14 +1291,21 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
case PassBy::CharBoxValueAttribute:
case PassBy::Box:
case PassBy::BaseAddress:
case PassBy::BoxProcRef:
case PassBy::BoxChar: {
PreparedDummyArgument preparedDummy = prepareUserCallActualArgument(
loc, builder, *preparedActual, argTy, arg, *expr, callContext);
callCleanUps.append(preparedDummy.cleanups.rbegin(),
preparedDummy.cleanups.rend());
caller.placeInput(arg, preparedDummy.dummy);
} break;
case PassBy::BoxProcRef: {
PreparedDummyArgument preparedDummy =
prepareProcedurePointerActualArgument(loc, builder, *preparedActual,
argTy, arg, *expr, callContext);
callCleanUps.append(preparedDummy.cleanups.rbegin(),
preparedDummy.cleanups.rend());
caller.placeInput(arg, preparedDummy.dummy);
} break;
case PassBy::AddressAndLength:
// PassBy::AddressAndLength is only used for character results. Results
// are not handled here.
Expand Down
5 changes: 4 additions & 1 deletion flang/lib/Lower/ConvertExprToHLFIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1219,8 +1219,11 @@ struct BinaryOp<Fortran::evaluate::SetLength<KIND>> {
fir::FirOpBuilder &builder, const Op &,
hlfir::Entity string,
hlfir::Entity length) {
// The input length may be a user input and needs to be sanitized as per
// Fortran 2018 7.4.4.2 point 5.
mlir::Value safeLength = fir::factory::genMaxWithZero(builder, loc, length);
return hlfir::EntityWithAttributes{
builder.create<hlfir::SetLengthOp>(loc, string, length)};
builder.create<hlfir::SetLengthOp>(loc, string, safeLength)};
}
static void
genResultTypeParams(mlir::Location, fir::FirOpBuilder &, hlfir::Entity,
Expand Down
26 changes: 9 additions & 17 deletions flang/lib/Lower/ConvertType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,19 +374,20 @@ struct TypeBuilderImpl {
mlir::Type genDerivedType(const Fortran::semantics::DerivedTypeSpec &tySpec) {
std::vector<std::pair<std::string, mlir::Type>> ps;
std::vector<std::pair<std::string, mlir::Type>> cs;
const Fortran::semantics::Symbol &typeSymbol = tySpec.typeSymbol();
if (mlir::Type ty = getTypeIfDerivedAlreadyInConstruction(typeSymbol))
return ty;

if (tySpec.IsVectorType()) {
return genVectorType(tySpec);
}

const Fortran::semantics::Symbol &typeSymbol = tySpec.typeSymbol();
const Fortran::semantics::Scope &derivedScope = DEREF(tySpec.GetScope());
if (mlir::Type ty = getTypeIfDerivedAlreadyInConstruction(derivedScope))
return ty;

auto rec = fir::RecordType::get(context, converter.mangleName(tySpec));
// Maintain the stack of types for recursive references.
derivedTypeInConstruction.emplace_back(typeSymbol, rec);
// Maintain the stack of types for recursive references and to speed-up
// the derived type constructions that can be expensive for derived type
// with dozens of components/parents (modern Fortran).
derivedTypeInConstruction.try_emplace(&derivedScope, rec);

// Gather the record type fields.
// (1) The data components.
Expand Down Expand Up @@ -446,7 +447,6 @@ struct TypeBuilderImpl {
}

rec.finalize(ps, cs);
popDerivedTypeInConstruction();

if (!ps.empty()) {
// TODO: this type is a PDT (parametric derived type) with length
Expand Down Expand Up @@ -552,16 +552,8 @@ struct TypeBuilderImpl {
/// type `t` have type `t`. This helper returns `t` if it is already being
/// lowered to avoid infinite loops.
mlir::Type getTypeIfDerivedAlreadyInConstruction(
const Fortran::lower::SymbolRef derivedSym) const {
for (const auto &[sym, type] : derivedTypeInConstruction)
if (sym == derivedSym)
return type;
return {};
}

void popDerivedTypeInConstruction() {
assert(!derivedTypeInConstruction.empty());
derivedTypeInConstruction.pop_back();
const Fortran::semantics::Scope &derivedScope) const {
return derivedTypeInConstruction.lookup(&derivedScope);
}

/// Stack derived type being processed to avoid infinite loops in case of
Expand Down
5 changes: 5 additions & 0 deletions flang/lib/Lower/DirectivesCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "flang/Lower/Support/Utils.h"
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "flang/Parser/parse-tree.h"
Expand Down Expand Up @@ -614,6 +615,10 @@ getDataOperandBaseAddr(Fortran::lower::AbstractConverter &converter,
fir::FirOpBuilder &builder,
Fortran::lower::SymbolRef sym, mlir::Location loc) {
mlir::Value symAddr = converter.getSymbolAddress(sym);
if (auto declareOp =
mlir::dyn_cast_or_null<hlfir::DeclareOp>(symAddr.getDefiningOp()))
symAddr = declareOp.getResults()[0];

// TODO: Might need revisiting to handle for non-shared clauses
if (!symAddr) {
if (const auto *details =
Expand Down
71 changes: 44 additions & 27 deletions flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,16 @@
#include "mlir/IR/OpImplementation.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/CommandLine.h"
#include <iterator>
#include <mlir/Interfaces/SideEffectInterfaces.h>
#include <optional>
#include <tuple>

static llvm::cl::opt<bool> useStrictIntrinsicVerifier(
"strict-intrinsic-verifier", llvm::cl::init(false),
llvm::cl::desc("use stricter verifier for HLFIR intrinsic operations"));

/// generic implementation of the memory side effects interface for hlfir
/// transformational intrinsic operations
static void
Expand Down Expand Up @@ -498,7 +503,7 @@ verifyLogicalReductionOp(LogicalReductionOp reductionOp) {
mlir::Type resultType = results[0];
if (mlir::isa<fir::LogicalType>(resultType)) {
// Result is of the same type as MASK
if (resultType != logicalTy)
if ((resultType != logicalTy) && useStrictIntrinsicVerifier)
return reductionOp->emitOpError(
"result must have the same element type as MASK argument");

Expand All @@ -509,7 +514,7 @@ verifyLogicalReductionOp(LogicalReductionOp reductionOp) {
if (!resultExpr.isArray())
return reductionOp->emitOpError("result must be an array");

if (resultExpr.getEleTy() != logicalTy)
if ((resultExpr.getEleTy() != logicalTy) && useStrictIntrinsicVerifier)
return reductionOp->emitOpError(
"result must have the same element type as MASK argument");

Expand Down Expand Up @@ -585,7 +590,7 @@ mlir::LogicalResult hlfir::CountOp::verify() {
if (resultShape.size() != (maskShape.size() - 1))
return emitOpError("result rank must be one less than MASK");
} else {
return emitOpError("result must be of numerical scalar type");
return emitOpError("result must be of numerical array type");
}
} else if (!hlfir::isFortranScalarNumericalType(resultType)) {
return emitOpError("result must be of numerical scalar type");
Expand Down Expand Up @@ -682,15 +687,18 @@ verifyArrayAndMaskForReductionOp(NumericalReductionOp reductionOp) {
if (!maskShape.empty()) {
if (maskShape.size() != arrayShape.size())
return reductionOp->emitWarning("MASK must be conformable to ARRAY");
static_assert(fir::SequenceType::getUnknownExtent() ==
hlfir::ExprType::getUnknownExtent());
constexpr int64_t unknownExtent = fir::SequenceType::getUnknownExtent();
for (std::size_t i = 0; i < arrayShape.size(); ++i) {
int64_t arrayExtent = arrayShape[i];
int64_t maskExtent = maskShape[i];
if ((arrayExtent != maskExtent) && (arrayExtent != unknownExtent) &&
(maskExtent != unknownExtent))
return reductionOp->emitWarning("MASK must be conformable to ARRAY");
if (useStrictIntrinsicVerifier) {
static_assert(fir::SequenceType::getUnknownExtent() ==
hlfir::ExprType::getUnknownExtent());
constexpr int64_t unknownExtent = fir::SequenceType::getUnknownExtent();
for (std::size_t i = 0; i < arrayShape.size(); ++i) {
int64_t arrayExtent = arrayShape[i];
int64_t maskExtent = maskShape[i];
if ((arrayExtent != maskExtent) && (arrayExtent != unknownExtent) &&
(maskExtent != unknownExtent))
return reductionOp->emitWarning(
"MASK must be conformable to ARRAY");
}
}
}
}
Expand Down Expand Up @@ -719,7 +727,7 @@ verifyNumericalReductionOp(NumericalReductionOp reductionOp) {
mlir::Type resultType = results[0];
if (hlfir::isFortranScalarNumericalType(resultType)) {
// Result is of the same type as ARRAY
if (resultType != numTy)
if ((resultType != numTy) && useStrictIntrinsicVerifier)
return reductionOp->emitOpError(
"result must have the same element type as ARRAY argument");

Expand All @@ -729,7 +737,7 @@ verifyNumericalReductionOp(NumericalReductionOp reductionOp) {
if (!resultExpr.isArray())
return reductionOp->emitOpError("result must be an array");

if (resultExpr.getEleTy() != numTy)
if ((resultExpr.getEleTy() != numTy) && useStrictIntrinsicVerifier)
return reductionOp->emitOpError(
"result must have the same element type as ARRAY argument");

Expand Down Expand Up @@ -792,7 +800,7 @@ verifyCharacterReductionOp(CharacterReductionOp reductionOp) {
"result must be character");

// Result is of the same type as ARRAY
if (resultType != numTy)
if ((resultType != numTy) && useStrictIntrinsicVerifier)
return reductionOp->emitOpError(
"result must have the same element type as ARRAY argument");

Expand Down Expand Up @@ -823,9 +831,8 @@ mlir::LogicalResult hlfir::MaxvalOp::verify() {
auto resultExpr = mlir::dyn_cast<hlfir::ExprType>(results[0]);
if (resultExpr && mlir::isa<fir::CharacterType>(resultExpr.getEleTy())) {
return verifyCharacterReductionOp<hlfir::MaxvalOp *>(this);
} else {
return verifyNumericalReductionOp<hlfir::MaxvalOp *>(this);
}
return verifyNumericalReductionOp<hlfir::MaxvalOp *>(this);
}

void hlfir::MaxvalOp::getEffects(
Expand All @@ -848,9 +855,8 @@ mlir::LogicalResult hlfir::MinvalOp::verify() {
auto resultExpr = mlir::dyn_cast<hlfir::ExprType>(results[0]);
if (resultExpr && mlir::isa<fir::CharacterType>(resultExpr.getEleTy())) {
return verifyCharacterReductionOp<hlfir::MinvalOp *>(this);
} else {
return verifyNumericalReductionOp<hlfir::MinvalOp *>(this);
}
return verifyNumericalReductionOp<hlfir::MinvalOp *>(this);
}

void hlfir::MinvalOp::getEffects(
Expand Down Expand Up @@ -1007,17 +1013,19 @@ mlir::LogicalResult hlfir::DotProductOp::verify() {

constexpr int64_t unknownExtent = fir::SequenceType::getUnknownExtent();
if ((lhsSize != unknownExtent) && (rhsSize != unknownExtent) &&
(lhsSize != rhsSize))
(lhsSize != rhsSize) && useStrictIntrinsicVerifier)
return emitOpError("both arrays must have the same size");

if (mlir::isa<fir::LogicalType>(lhsEleTy) !=
mlir::isa<fir::LogicalType>(rhsEleTy))
return emitOpError("if one array is logical, so should the other be");
if (useStrictIntrinsicVerifier) {
if (mlir::isa<fir::LogicalType>(lhsEleTy) !=
mlir::isa<fir::LogicalType>(rhsEleTy))
return emitOpError("if one array is logical, so should the other be");

if (mlir::isa<fir::LogicalType>(lhsEleTy) !=
mlir::isa<fir::LogicalType>(resultTy))
return emitOpError("the result type should be a logical only if the "
"argument types are logical");
if (mlir::isa<fir::LogicalType>(lhsEleTy) !=
mlir::isa<fir::LogicalType>(resultTy))
return emitOpError("the result type should be a logical only if the "
"argument types are logical");
}

if (!hlfir::isFortranScalarNumericalType(resultTy) &&
!mlir::isa<fir::LogicalType>(resultTy))
Expand Down Expand Up @@ -1067,6 +1075,9 @@ mlir::LogicalResult hlfir::MatmulOp::verify() {
mlir::isa<fir::LogicalType>(rhsEleTy))
return emitOpError("if one array is logical, so should the other be");

if (!useStrictIntrinsicVerifier)
return mlir::success();

int64_t lastLhsDim = lhsShape[lhsRank - 1];
int64_t firstRhsDim = rhsShape[0];
constexpr int64_t unknownExtent = fir::SequenceType::getUnknownExtent();
Expand Down Expand Up @@ -1179,6 +1190,9 @@ mlir::LogicalResult hlfir::TransposeOp::verify() {
if (rank != 2 || resultRank != 2)
return emitOpError("input and output arrays should have rank 2");

if (!useStrictIntrinsicVerifier)
return mlir::success();

constexpr int64_t unknownExtent = fir::SequenceType::getUnknownExtent();
if ((inShape[0] != resultShape[1]) && (inShape[0] != unknownExtent))
return emitOpError("output shape does not match input array");
Expand Down Expand Up @@ -1226,6 +1240,9 @@ mlir::LogicalResult hlfir::MatmulTransposeOp::verify() {
if ((lhsRank != 2) || ((rhsRank != 1) && (rhsRank != 2)))
return emitOpError("array must have either rank 1 or rank 2");

if (!useStrictIntrinsicVerifier)
return mlir::success();

if (mlir::isa<fir::LogicalType>(lhsEleTy) !=
mlir::isa<fir::LogicalType>(rhsEleTy))
return emitOpError("if one array is logical, so should the other be");
Expand Down
4 changes: 2 additions & 2 deletions flang/test/HLFIR/invalid.fir
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// HLFIR ops diagnotic tests

// RUN: fir-opt -split-input-file -verify-diagnostics %s
// RUN: fir-opt -strict-intrinsic-verifier -split-input-file -verify-diagnostics %s

func.func @bad_declare(%arg0: !fir.ref<f32>) {
// expected-error@+1 {{'hlfir.declare' op first result type is inconsistent with variable properties: expected '!fir.ref<f32>'}}
Expand Down Expand Up @@ -382,7 +382,7 @@ func.func @bad_count2(%arg0: !hlfir.expr<?x?x!fir.logical<4>>, %arg1: i32){

// -----
func.func @bad_count3(%arg0: !hlfir.expr<?x!fir.logical<4>>, %arg1: i32) {
// expected-error@+1 {{'hlfir.count' op result must be of numerical scalar type}}
// expected-error@+1 {{'hlfir.count' op result must be of numerical array type}}
%0 = hlfir.count %arg0 dim %arg1 : (!hlfir.expr<?x!fir.logical<4>>, i32) -> !hlfir.expr<i32>
}

Expand Down
14 changes: 14 additions & 0 deletions flang/test/Lower/HLFIR/array-ctor-character.f90
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,17 @@ subroutine takes_char(c)
print *, "expect: abcdef"
call test_dynamic_length()
end

subroutine test_set_length_sanitize(i, c1)
integer(8) :: i
character(*) :: c1
call takes_char([character(len=i):: c1])
end subroutine
! CHECK-LABEL: func.func @_QPtest_set_length_sanitize(
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare {{.*}}Ec1
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare {{.*}}Ei
! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_26:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_27:.*]] = arith.cmpi sgt, %[[VAL_25]], %[[VAL_26]] : i64
! CHECK: %[[VAL_28:.*]] = arith.select %[[VAL_27]], %[[VAL_25]], %[[VAL_26]] : i64
! CHECK: %[[VAL_29:.*]] = hlfir.set_length %[[VAL_6]]#0 len %[[VAL_28]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,?>>
44 changes: 44 additions & 0 deletions flang/test/Lower/HLFIR/minval.f90
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,47 @@ end subroutine test_unknown_char_len_result
! CHECK-NEXT: hlfir.destroy %[[EXPR]]
! CHECK-NEXT: return
! CHECK-NEXT: }

! Test edge case with missmatch between argument type !fir.char<1,?> and result
! type !fir.char<1,4>
function test_type_mismatch
character(:), allocatable :: test_type_mismatch(:)
character(3) :: char(3,4)
test_type_mismatch = minval(char//' ', dim=1)
end function
! CHECK-LABEL: func.func @_QPtest_type_mismatch() -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>> {
! CHECK: %[[VAL_0:.*]] = arith.constant 3 : index
! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index
! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<3x4x!fir.char<1,3>> {bindc_name = "char", uniq_name = "_QFtest_type_mismatchEchar"}
! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2>
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_4]]) typeparams %[[VAL_0]] {uniq_name = "_QFtest_type_mismatchEchar"} : (!fir.ref<!fir.array<3x4x!fir.char<1,3>>>, !fir.shape<2>, index) -> (!fir.ref<!fir.array<3x4x!fir.char<1,3>>>, !fir.ref<!fir.array<3x4x!fir.char<1,3>>>)
! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>> {bindc_name = "test_type_mismatch", uniq_name = "_QFtest_type_mismatchEtest_type_mismatch"}
! CHECK: %[[VAL_7:.*]] = fir.zero_bits !fir.heap<!fir.array<?x!fir.char<1,?>>>
! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_10:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_7]](%[[VAL_9]]) typeparams %[[VAL_10]] : (!fir.heap<!fir.array<?x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_6]] {fortran_attrs = #{{.*}}, uniq_name = "_QFtest_type_mismatchEtest_type_mismatch"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>)
! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX20) : !fir.ref<!fir.char<1>>
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] typeparams %[[VAL_14]] {fortran_attrs = {{.*}}, uniq_name = "_QQclX20"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
! CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_0]], %[[VAL_14]] : index
! CHECK: %[[VAL_17:.*]] = hlfir.elemental %[[VAL_4]] typeparams %[[VAL_16]] unordered : (!fir.shape<2>, index) -> !hlfir.expr<3x4x!fir.char<1,?>> {
! CHECK: ^bb0(%[[VAL_18:.*]]: index, %[[VAL_19:.*]]: index):
! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_18]], %[[VAL_19]]) typeparams %[[VAL_0]] : (!fir.ref<!fir.array<3x4x!fir.char<1,3>>>, index, index, index) -> !fir.ref<!fir.char<1,3>>
! CHECK: %[[VAL_21:.*]] = hlfir.concat %[[VAL_20]], %[[VAL_15]]#0 len %[[VAL_16]] : (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1>>, index) -> !hlfir.expr<!fir.char<1,4>>
! CHECK: hlfir.yield_element %[[VAL_21]] : !hlfir.expr<!fir.char<1,4>>
! CHECK: }
! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_23:.*]] = hlfir.minval %[[VAL_17]] dim %[[VAL_22]] {fastmath = {{.*}}} : (!hlfir.expr<3x4x!fir.char<1,?>>, i32) -> !hlfir.expr<4x!fir.char<1,4>>
! CHECK: hlfir.assign %[[VAL_23]] to %[[VAL_12]]#0 realloc : !hlfir.expr<4x!fir.char<1,4>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
! CHECK: hlfir.destroy %[[VAL_23]] : !hlfir.expr<4x!fir.char<1,4>>
! CHECK: hlfir.destroy %[[VAL_17]] : !hlfir.expr<3x4x!fir.char<1,?>>
! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
! CHECK: %[[VAL_25:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_26:.*]] = fir.shift %[[VAL_25]] : (index) -> !fir.shift<1>
! CHECK: %[[VAL_27:.*]] = fir.rebox %[[VAL_24]](%[[VAL_26]]) : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>, !fir.shift<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
! CHECK: return %[[VAL_27]] : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
! CHECK: }
20 changes: 20 additions & 0 deletions flang/test/Lower/HLFIR/procedure-pointer.f90
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,26 @@ subroutine sub12()
! CHECK: fir.call @_QPfoo2(%[[VAL_17]]) fastmath<contract> : (!fir.ref<!fir.boxproc<() -> ()>>) -> ()
end

subroutine test_opt_pointer()
interface
subroutine takes_opt_proc_ptr(p)
procedure(), pointer, optional :: p
end subroutine
end interface
call takes_opt_proc_ptr(NULL())
call takes_opt_proc_ptr()
end subroutine
! CHECK-LABEL: func.func @_QPtest_opt_pointer() {
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.boxproc<() -> ()>
! CHECK: %[[VAL_1:.*]] = fir.zero_bits () -> ()
! CHECK: %[[VAL_2:.*]] = fir.emboxproc %[[VAL_1]] : (() -> ()) -> !fir.boxproc<() -> ()>
! CHECK: fir.store %[[VAL_2]] to %[[VAL_0]] : !fir.ref<!fir.boxproc<() -> ()>>
! CHECK: fir.call @_QPtakes_opt_proc_ptr(%[[VAL_0]]) fastmath<contract> : (!fir.ref<!fir.boxproc<() -> ()>>) -> ()
! CHECK: %[[VAL_3:.*]] = fir.absent !fir.ref<!fir.boxproc<() -> ()>>
! CHECK: fir.call @_QPtakes_opt_proc_ptr(%[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.boxproc<() -> ()>>) -> ()



! CHECK-LABEL: fir.global internal @_QFsub1Ep2 : !fir.boxproc<(!fir.ref<f32>) -> f32> {
! CHECK: %[[VAL_0:.*]] = fir.zero_bits (!fir.ref<f32>) -> f32
! CHECK: %[[VAL_1:.*]] = fir.emboxproc %[[VAL_0]] : ((!fir.ref<f32>) -> f32) -> !fir.boxproc<(!fir.ref<f32>) -> f32>
Expand Down
22 changes: 12 additions & 10 deletions flang/test/Lower/OpenACC/acc-bounds.f90
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,15 @@ subroutine acc_undefined_extent(a)
!$acc kernels present(a)
!$acc end kernels
end subroutine

! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_undefined_extent(
! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a"}) {
! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) {uniq_name = "_QMopenacc_boundsFacc_undefined_extentEa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>)
! CHECK: %[[ONE:.*]] = arith.constant 1 : index
! CHECK: %[[ZERO:.*]] = arith.constant 0 : index
! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[ZERO]] : index) extent(%[[ZERO]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index)
! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[DECL_ARG0]]#1 : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a"}
! CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
! CHECK: %[[UB:.*]] = arith.subi %[[DIMS0]]#1, %c1{{.*}} : index
! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%c1{{.*}} : index) {strideInBytes = true}
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECL_ARG0]]#0 : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a"}
! CHECK: acc.kernels dataOperands(%[[PRESENT]] : !fir.ref<!fir.array<?xf32>>)

subroutine acc_multi_strides(a)
Expand All @@ -104,15 +106,15 @@ subroutine acc_multi_strides(a)
! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_multi_strides(
! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "a"})
! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QMopenacc_boundsFacc_multi_stridesEa"} : (!fir.box<!fir.array<?x?x?xf32>>) -> (!fir.box<!fir.array<?x?x?xf32>>, !fir.box<!fir.array<?x?x?xf32>>)
! CHECK: %[[BOX_DIMS0:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#1, %c0{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
! CHECK: %[[BOX_DIMS0:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c0{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
! CHECK: %[[BOUNDS0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS0]]#1 : index) stride(%[[BOX_DIMS0]]#2 : index) startIdx(%{{.*}} : index) {strideInBytes = true}
! CHECK: %[[STRIDE1:.*]] = arith.muli %[[BOX_DIMS0]]#2, %[[BOX_DIMS0]]#1 : index
! CHECK: %[[BOX_DIMS1:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#1, %c1{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
! CHECK: %[[BOX_DIMS1:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c1{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
! CHECK: %[[BOUNDS1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS1]]#1 : index) stride(%[[STRIDE1]] : index) startIdx(%{{.*}} : index) {strideInBytes = true}
! CHECK: %[[STRIDE2:.*]] = arith.muli %[[STRIDE1]], %[[BOX_DIMS1]]#1 : index
! CHECK: %[[BOX_DIMS2:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#1, %c2{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
! CHECK: %[[BOX_DIMS2:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c2{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
! CHECK: %[[BOUNDS2:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS2]]#1 : index) stride(%[[STRIDE2]] : index) startIdx(%{{.*}} : index) {strideInBytes = true}
! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL_ARG0]]#1 : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL_ARG0]]#0 : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?x?x?xf32>>) bounds(%29, %33, %37) -> !fir.ref<!fir.array<?x?x?xf32>> {name = "a"}
! CHECK: acc.kernels dataOperands(%[[PRESENT]] : !fir.ref<!fir.array<?x?x?xf32>>) {

Expand All @@ -125,9 +127,9 @@ subroutine acc_optional_data(a)
! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_optional_data(
! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "a", fir.optional}) {
! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QMopenacc_boundsFacc_optional_dataEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>)
! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[ARG0_DECL]]#1 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> i1
! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[ARG0_DECL]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> i1
! CHECK: %[[BOX:.*]] = fir.if %[[IS_PRESENT]] -> (!fir.box<!fir.ptr<!fir.array<?xf32>>>) {
! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0_DECL]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
! CHECK: fir.result %[[LOAD]] : !fir.box<!fir.ptr<!fir.array<?xf32>>>
! CHECK: } else {
! CHECK: %[[ABSENT:.*]] = fir.absent !fir.box<!fir.ptr<!fir.array<?xf32>>>
Expand Down
Loading