84 changes: 51 additions & 33 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cassert>
Expand Down Expand Up @@ -5925,11 +5926,9 @@ QualType ASTContext::getUnconstrainedType(QualType T) const {
return T;
}

/// Return the uniqued reference to the deduced template specialization type
/// which has been deduced to the given type, or to the canonical undeduced
/// such type, or the canonical deduced-but-dependent such type.
QualType ASTContext::getDeducedTemplateSpecializationType(
TemplateName Template, QualType DeducedType, bool IsDependent) const {
QualType ASTContext::getDeducedTemplateSpecializationTypeInternal(
TemplateName Template, QualType DeducedType, bool IsDependent,
QualType Canon) const {
// Look in the folding set for an existing type.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
Expand All @@ -5940,7 +5939,8 @@ QualType ASTContext::getDeducedTemplateSpecializationType(
return QualType(DTST, 0);

auto *DTST = new (*this, alignof(DeducedTemplateSpecializationType))
DeducedTemplateSpecializationType(Template, DeducedType, IsDependent);
DeducedTemplateSpecializationType(Template, DeducedType, IsDependent,
Canon);
llvm::FoldingSetNodeID TempID;
DTST->Profile(TempID);
assert(ID == TempID && "ID does not match");
Expand All @@ -5949,6 +5949,20 @@ QualType ASTContext::getDeducedTemplateSpecializationType(
return QualType(DTST, 0);
}

/// Return the uniqued reference to the deduced template specialization type
/// which has been deduced to the given type, or to the canonical undeduced
/// such type, or the canonical deduced-but-dependent such type.
QualType ASTContext::getDeducedTemplateSpecializationType(
TemplateName Template, QualType DeducedType, bool IsDependent) const {
QualType Canon = DeducedType.isNull()
? getDeducedTemplateSpecializationTypeInternal(
getCanonicalTemplateName(Template), QualType(),
IsDependent, QualType())
: DeducedType.getCanonicalType();
return getDeducedTemplateSpecializationTypeInternal(Template, DeducedType,
IsDependent, Canon);
}

/// getAtomicType - Return the uniqued reference to the atomic type for
/// the given value type.
QualType ASTContext::getAtomicType(QualType T) const {
Expand Down Expand Up @@ -13663,17 +13677,20 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const {
}
}

std::vector<std::string> ASTContext::filterFunctionTargetVersionAttrs(
const TargetVersionAttr *TV) const {
assert(TV != nullptr);
llvm::SmallVector<StringRef, 8> Feats;
std::vector<std::string> ResFeats;
TV->getFeatures(Feats);
for (auto &Feature : Feats)
if (Target->validateCpuSupports(Feature.str()))
// Use '?' to mark features that came from TargetVersion.
ResFeats.push_back("?" + Feature.str());
return ResFeats;
// Given a list of FMV features, return a concatenated list of the
// corresponding backend features (which may contain duplicates).
static std::vector<std::string> getFMVBackendFeaturesFor(
const llvm::SmallVectorImpl<StringRef> &FMVFeatStrings) {
std::vector<std::string> BackendFeats;
for (StringRef F : FMVFeatStrings) {
if (auto FMVExt = llvm::AArch64::parseArchExtension(F)) {
SmallVector<StringRef, 8> Feats;
FMVExt->DependentFeatures.split(Feats, ',', -1, false);
for (StringRef F : Feats)
BackendFeats.push_back(F.str());
}
}
return BackendFeats;
}

ParsedTargetAttr
Expand Down Expand Up @@ -13708,10 +13725,12 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,

// Make a copy of the features as passed on the command line into the
// beginning of the additional features from the function to override.
ParsedAttr.Features.insert(
ParsedAttr.Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
// AArch64 handles command line option features in parseTargetAttr().
if (!Target->getTriple().isAArch64())
ParsedAttr.Features.insert(
ParsedAttr.Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());

if (ParsedAttr.CPU != "" && Target->isValidCPUName(ParsedAttr.CPU))
TargetCPU = ParsedAttr.CPU;
Expand All @@ -13732,32 +13751,31 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
Target->getTargetOpts().FeaturesAsWritten.end());
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
} else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) {
std::vector<std::string> Features;
if (Target->getTriple().isAArch64()) {
// TargetClones for AArch64
llvm::SmallVector<StringRef, 8> Feats;
TC->getFeatures(Feats, GD.getMultiVersionIndex());
for (StringRef Feat : Feats)
if (Target->validateCpuSupports(Feat.str()))
// Use '?' to mark features that came from AArch64 TargetClones.
Features.push_back("?" + Feat.str());
std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats);
Features.insert(Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
} else {
std::vector<std::string> Features;
StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex());
if (VersionStr.starts_with("arch="))
TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1);
else if (VersionStr != "default")
Features.push_back((StringRef{"+"} + VersionStr).str());
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
}
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
} else if (const auto *TV = FD->getAttr<TargetVersionAttr>()) {
std::vector<std::string> Feats = filterFunctionTargetVersionAttrs(TV);
Feats.insert(Feats.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Feats);
llvm::SmallVector<StringRef, 8> Feats;
TV->getFeatures(Feats);
std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats);
Features.insert(Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
} else {
FeatureMap = Target->getTargetOpts().FeatureMap;
}
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/AST/ASTStructuralEquivalence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,15 @@ class StmtComparer {
return true;
}

bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1,
const CXXDependentScopeMemberExpr *E2) {
if (!IsStructurallyEquivalent(Context, E1->getMember(), E2->getMember())) {
return false;
}
return IsStructurallyEquivalent(Context, E1->getBaseType(),
E2->getBaseType());
}

bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1,
const UnaryExprOrTypeTraitExpr *E2) {
if (E1->getKind() != E2->getKind())
Expand Down Expand Up @@ -1997,7 +2006,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
return false;
}

if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth())
return false;
if (D1->getIndex() != D2->getIndex())
return false;
// Check types.
if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
if (Context.Complain) {
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,6 @@ add_clang_library(clangAST
omp_gen
ClangDriverOptions
intrinsics_gen
# These generated headers are included transitively.
AArch64TargetParserTableGen
)
10 changes: 6 additions & 4 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3223,6 +3223,8 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
assert(!DiscardResult);
if (Val.isInt())
return this->emitConst(Val.getInt(), ValType, E);
else if (Val.isFloat())
return this->emitConstFloat(Val.getFloat(), E);

if (Val.isLValue()) {
if (Val.isNullPointer())
Expand Down Expand Up @@ -3253,7 +3255,7 @@ bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
const APValue &F = Val.getStructField(I);
const Record::Field *RF = R->getField(I);

if (F.isInt() || F.isLValue() || F.isMemberPointer()) {
if (F.isInt() || F.isFloat() || F.isLValue() || F.isMemberPointer()) {
PrimType T = classifyPrim(RF->Decl->getType());
if (!this->visitAPValue(F, T, E))
return false;
Expand Down Expand Up @@ -3948,7 +3950,7 @@ bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
if (const auto *VD = dyn_cast<VarDecl>(D)) {
// Visit local const variables like normal.
if ((VD->isLocalVarDecl() || VD->isStaticDataMember()) &&
VD->getType().isConstQualified()) {
VD->getType().isConstant(Ctx.getASTContext())) {
if (!this->visitVarDecl(VD))
return false;
// Retry.
Expand All @@ -3957,8 +3959,8 @@ bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
}
} else {
if (const auto *VD = dyn_cast<VarDecl>(D);
VD && VD->getAnyInitializer() && VD->getType().isConstQualified() &&
!VD->isWeak()) {
VD && VD->getAnyInitializer() &&
VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak()) {
if (!this->visitVarDecl(VD))
return false;
// Retry.
Expand Down
9 changes: 0 additions & 9 deletions clang/lib/AST/TemplateName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,6 @@ bool TemplateName::containsUnexpandedParameterPack() const {
return getDependence() & TemplateNameDependence::UnexpandedPack;
}

void TemplateName::Profile(llvm::FoldingSetNodeID &ID) {
if (const auto* USD = getAsUsingShadowDecl())
ID.AddPointer(USD->getCanonicalDecl());
else if (const auto *TD = getAsTemplateDecl())
ID.AddPointer(TD->getCanonicalDecl());
else
ID.AddPointer(Storage.getOpaqueValue());
}

void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Qualified Qual) const {
auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) {
Expand Down
105 changes: 33 additions & 72 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1052,57 +1052,18 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
return true;
}

bool AArch64TargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeaturesVec) const {
std::vector<std::string> UpdatedFeaturesVec;
// Parse the CPU and add any implied features.
std::optional<llvm::AArch64::CpuInfo> CpuInfo = llvm::AArch64::parseCpu(CPU);
if (CpuInfo) {
auto Exts = CpuInfo->getImpliedExtensions();
std::vector<StringRef> CPUFeats;
llvm::AArch64::getExtensionFeatures(Exts, CPUFeats);
for (auto F : CPUFeats) {
assert((F[0] == '+' || F[0] == '-') && "Expected +/- in target feature!");
UpdatedFeaturesVec.push_back(F.str());
}
}

// Process target and dependent features. This is done in two loops collecting
// them into UpdatedFeaturesVec: first to add dependent '+'features, second to
// add target '+/-'features that can later disable some of features added on
// the first loop. Function Multi Versioning features begin with '?'.
for (const auto &Feature : FeaturesVec)
if (((Feature[0] == '?' || Feature[0] == '+')) &&
AArch64TargetInfo::doesFeatureAffectCodeGen(Feature.substr(1))) {
StringRef DepFeatures =
AArch64TargetInfo::getFeatureDependencies(Feature.substr(1));
SmallVector<StringRef, 1> AttrFeatures;
DepFeatures.split(AttrFeatures, ",");
for (auto F : AttrFeatures)
UpdatedFeaturesVec.push_back(F.str());
}
for (const auto &Feature : FeaturesVec)
if (Feature[0] != '?') {
std::string UpdatedFeature = Feature;
if (Feature[0] == '+') {
std::optional<llvm::AArch64::ExtensionInfo> Extension =
llvm::AArch64::parseArchExtension(Feature.substr(1));
if (Extension)
UpdatedFeature = Extension->Feature.str();
}
UpdatedFeaturesVec.push_back(UpdatedFeature);
}

return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
}

// Parse AArch64 Target attributes, which are a comma separated list of:
// "arch=<arch>" - parsed to features as per -march=..
// "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
// "tune=<cpu>" - TuneCPU set to <cpu>
// "feature", "no-feature" - Add (or remove) feature.
// "+feature", "+nofeature" - Add (or remove) feature.
//
// A feature may correspond to an Extension (anything with a corresponding
// AEK_), in which case an ExtensionSet is used to parse it and expand its
// dependencies. Otherwise the feature is passed through (e.g. +v8.1a,
// +outline-atomics, -fmv, etc). Features coming from the command line are
// already parsed, therefore their dependencies do not need expansion.
ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
ParsedTargetAttr Ret;
if (Features == "default")
Expand All @@ -1112,23 +1073,26 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
bool FoundArch = false;

auto SplitAndAddFeatures = [](StringRef FeatString,
std::vector<std::string> &Features) {
std::vector<std::string> &Features,
llvm::AArch64::ExtensionSet &FeatureBits) {
SmallVector<StringRef, 8> SplitFeatures;
FeatString.split(SplitFeatures, StringRef("+"), -1, false);
for (StringRef Feature : SplitFeatures) {
StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
if (!FeatureName.empty())
Features.push_back(FeatureName.str());
if (FeatureBits.parseModifier(Feature, /* AllowNoDashForm = */ true))
continue;
// Pass through features that are not extensions, e.g. +v8.1a,
// +outline-atomics, -fmv, etc.
if (Feature.starts_with("no"))
Features.push_back("-" + Feature.drop_front(2).str());
else
// Pushing the original feature string to give a sema error later on
// when they get checked.
if (Feature.starts_with("no"))
Features.push_back("-" + Feature.drop_front(2).str());
else
Features.push_back("+" + Feature.str());
Features.push_back("+" + Feature.str());
}
};

llvm::AArch64::ExtensionSet FeatureBits;
// Reconstruct the bitset from the command line option features.
FeatureBits.reconstructFromParsedFeatures(getTargetOpts().FeaturesAsWritten);

for (auto &Feature : AttrFeatures) {
Feature = Feature.trim();
if (Feature.starts_with("fpmath="))
Expand All @@ -1151,9 +1115,9 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
// Ret.Features.
if (!AI)
continue;
Ret.Features.push_back(AI->ArchFeature.str());
FeatureBits.addArchDefaults(*AI);
// Add any extra features, after the +
SplitAndAddFeatures(Split.second, Ret.Features);
SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
} else if (Feature.starts_with("cpu=")) {
if (!Ret.CPU.empty())
Ret.Duplicate = "cpu=";
Expand All @@ -1163,33 +1127,30 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
std::pair<StringRef, StringRef> Split =
Feature.split("=").second.trim().split("+");
Ret.CPU = Split.first;
SplitAndAddFeatures(Split.second, Ret.Features);
if (auto CpuInfo = llvm::AArch64::parseCpu(Ret.CPU)) {
FeatureBits.addCPUDefaults(*CpuInfo);
SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
}
}
} else if (Feature.starts_with("tune=")) {
if (!Ret.Tune.empty())
Ret.Duplicate = "tune=";
else
Ret.Tune = Feature.split("=").second.trim();
} else if (Feature.starts_with("+")) {
SplitAndAddFeatures(Feature, Ret.Features);
} else if (Feature.starts_with("no-")) {
StringRef FeatureName =
llvm::AArch64::getArchExtFeature(Feature.split("-").second);
if (!FeatureName.empty())
Ret.Features.push_back("-" + FeatureName.drop_front(1).str());
else
Ret.Features.push_back("-" + Feature.split("-").second.str());
SplitAndAddFeatures(Feature, Ret.Features, FeatureBits);
} else {
// Try parsing the string to the internal target feature name. If it is
// invalid, add the original string (which could already be an internal
// name). These should be checked later by isValidFeatureName.
StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
if (!FeatureName.empty())
Ret.Features.push_back(FeatureName.str());
if (FeatureBits.parseModifier(Feature, /* AllowNoDashForm = */ true))
continue;
// Pass through features that are not extensions, e.g. +v8.1a,
// +outline-atomics, -fmv, etc.
if (Feature.starts_with("no-"))
Ret.Features.push_back("-" + Feature.drop_front(3).str());
else
Ret.Features.push_back("+" + Feature.str());
}
}
FeatureBits.toLLVMFeatureList(Ret.Features);
return Ret;
}

Expand Down
4 changes: 0 additions & 4 deletions clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,6 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
unsigned multiVersionSortPriority(StringRef Name) const override;
unsigned multiVersionFeatureCost() const override;

bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override;
bool useFP16ConversionIntrinsics() const override {
return false;
}
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/CodeGen/CGCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) {

assert(rv.isAggregate());
Address V = rv.getAggregateAddress();
return saved_type(
DominatingValue<Address>::save(CGF, V), rv.isVolatileQualified(),
DominatingValue<Address>::needsSaving(V) ? AggregateAddress
: AggregateLiteral);
return saved_type(DominatingValue<Address>::save(CGF, V),
DominatingValue<Address>::needsSaving(V)
? AggregateAddress
: AggregateLiteral);
}

/// Given a saved r-value produced by SaveRValue, perform the code
Expand All @@ -65,7 +65,7 @@ RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
case AggregateLiteral:
case AggregateAddress:
return RValue::getAggregate(
DominatingValue<Address>::restore(CGF, AggregateAddr), IsVolatile);
DominatingValue<Address>::restore(CGF, AggregateAddr));
case ComplexAddress: {
llvm::Value *real = DominatingLLVMValue::restore(CGF, Vals.first);
llvm::Value *imag = DominatingLLVMValue::restore(CGF, Vals.second);
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ template <> struct DominatingValue<RValue> {
};
LLVM_PREFERRED_TYPE(Kind)
unsigned K : 3;
unsigned IsVolatile : 1;

saved_type(DominatingLLVMValue::saved_type Val1, unsigned K)
: Vals{Val1, DominatingLLVMValue::saved_type()}, K(K) {}
Expand All @@ -230,8 +229,7 @@ template <> struct DominatingValue<RValue> {
DominatingLLVMValue::saved_type Val2)
: Vals{Val1, Val2}, K(ComplexAddress) {}

saved_type(DominatingValue<Address>::saved_type AggregateAddr,
bool IsVolatile, unsigned K)
saved_type(DominatingValue<Address>::saved_type AggregateAddr, unsigned K)
: AggregateAddr(AggregateAddr), K(K) {}

public:
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,14 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
if (VFS->setCurrentWorkingDirectory(WD->getValue()))
Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();

// Check for missing include directories.
if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {
for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {
if (!VFS->exists(IncludeDir))
Diag(diag::warn_missing_include_dirs) << IncludeDir;
}
}

// FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintPhases;

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ ||
IsLoongArch64 || IsRISCV64)
Res |= SanitizerKind::Thread;
if (IsX86_64 || IsSystemZ)
if (IsX86_64 || IsSystemZ || IsPowerPC64)
Res |= SanitizerKind::KernelMemory;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch ||
IsPowerPC64 || IsHexagon || IsLoongArch64 || IsRISCV64)
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2257,6 +2257,8 @@ bool UnwrappedLineParser::tryToParseLambda() {
break;
case tok::kw_auto:
case tok::kw_class:
case tok::kw_struct:
case tok::kw_union:
case tok::kw_template:
case tok::kw_typename:
case tok::amp:
Expand Down
1 change: 0 additions & 1 deletion clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ add_clang_library(clangStaticAnalyzerCheckers
CheckObjCInstMethSignature.cpp
CheckPlacementNew.cpp
CheckSecuritySyntaxOnly.cpp
CheckSizeofPointer.cpp
CheckerDocumentation.cpp
ChrootChecker.cpp
CloneChecker.cpp
Expand Down
96 changes: 0 additions & 96 deletions clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp

This file was deleted.

7 changes: 7 additions & 0 deletions clang/test/AST/Interp/opencl.cl
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,10 @@ void negativeShift32(int a,int b) {

int2 A = {1,2};
int4 B = {(int2)(1,2), (int2)(3,4)};


constant int sz0 = 5;
kernel void testvla()
{
int vla0[sz0];
}
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1479,4 +1479,17 @@ namespace VirtOperator {
};
constexpr bool cmp_base_derived = D() == D(); // both-warning {{ambiguous}}
}

namespace FloatAPValue {
struct ClassTemplateArg {
int a;
float f;
};
template<ClassTemplateArg A> struct ClassTemplateArgTemplate {
static constexpr const ClassTemplateArg &Arg = A;
};
ClassTemplateArgTemplate<ClassTemplateArg{1, 2.0f}> ClassTemplateArgObj;
template<const ClassTemplateArg&> struct ClassTemplateArgRefTemplate {};
ClassTemplateArgRefTemplate<ClassTemplateArgObj.Arg> ClassTemplateArgRefObj;
}
#endif
8 changes: 0 additions & 8 deletions clang/test/Analysis/sizeofpointer.c

This file was deleted.

4 changes: 2 additions & 2 deletions clang/test/CodeGen/aarch64-cpu-supports-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ int test_versions() {
return code();
}
// CHECK: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon" }
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" }
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" }
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme \
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +bf16 \
// RUN: -disable-O0-optnone -Werror -emit-llvm -o - %s \
// RUN: | opt -S -passes=mem2reg \
// RUN: | opt -S -passes=inline \
Expand Down
48 changes: 20 additions & 28 deletions clang/test/CodeGen/aarch64-targetattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,58 +58,50 @@ void v1msve() {}
// CHECK-LABEL: @plussve() #12
__attribute__((target("+sve")))
void plussve() {}
// CHECK-LABEL: @plussveplussve2() #13
// CHECK-LABEL: @plussveplussve2() #12
__attribute__((target("+sve+nosve2")))
void plussveplussve2() {}
// CHECK-LABEL: @plussveminusnosve2() #13
// CHECK-LABEL: @plussveminusnosve2() #12
__attribute__((target("sve,no-sve2")))
void plussveminusnosve2() {}
// CHECK-LABEL: @plusfp16() #14
// CHECK-LABEL: @plusfp16() #13
__attribute__((target("+fp16")))
void plusfp16() {}

// CHECK-LABEL: @all() #15
// CHECK-LABEL: @all() #14
__attribute__((target("cpu=neoverse-n1,tune=cortex-a710,arch=armv8.6-a+sve2")))
void all() {}
// CHECK-LABEL: @allplusbranchprotection() #16
// CHECK-LABEL: @allplusbranchprotection() #15
__attribute__((target("cpu=neoverse-n1,tune=cortex-a710,arch=armv8.6-a+sve2,branch-protection=standard")))
void allplusbranchprotection() {}

// These tests check that the user facing and internal llvm name are both accepted.
// CHECK-LABEL: @plusnoneon() #17
__attribute__((target("+noneon")))
void plusnoneon() {}
// CHECK-LABEL: @plusnosimd() #17
// CHECK-LABEL: @plusnosimd() #16
__attribute__((target("+nosimd")))
void plusnosimd() {}
// CHECK-LABEL: @noneon() #17
__attribute__((target("no-neon")))
void noneon() {}
// CHECK-LABEL: @nosimd() #17
// CHECK-LABEL: @nosimd() #16
__attribute__((target("no-simd")))
void nosimd() {}

// This isn't part of the standard interface, but test that -arch features should not apply anything else.
// CHECK-LABEL: @minusarch() #18
// CHECK-LABEL: @minusarch() #17
__attribute__((target("no-v9.3a")))
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,+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 #3 = { {{.*}} "target-features"="+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+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,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a" }
// 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,+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,+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" }
// CHECK: attributes #8 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+v8.1a,+v8.2a,+v8a" "tune-cpu"="cortex-a710" }
// CHECK: attributes #9 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+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,+pauth,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a" }
// 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,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,-sve" }
// CHECK: attributes #12 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+sve" }
// CHECK: attributes #13 = { {{.*}} "target-features"="+fp-armv8,+fullfp16" }
// CHECK: attributes #14 = { {{.*}} "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 #15 = { {{.*}} "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-NOT: attributes #16 = {{.*}} "target-features"
// CHECK: attributes #17 = { {{.*}} "target-features"="-v9.3a" }
46 changes: 23 additions & 23 deletions clang/test/CodeGen/attr-target-version.c
Original file line number Diff line number Diff line change
Expand Up @@ -1129,42 +1129,42 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
// CHECK-NOFMV-NEXT: ret i32 0
//
//.
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp16fml,+fullfp16,+neon,+rand,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp-armv8,+fp16fml,+fullfp16,+neon,+rand,-v9.5a" }
// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+sme,+sme-i16i64,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+sha2,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+ls64,+neon,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp16fml,+fullfp16,+neon,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon,+sha2,-v9.5a" }
// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+ls64,+neon,-v9.5a" }
// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fp16fml,+fullfp16,+neon,-v9.5a" }
// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,-v9.5a" }
// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme2,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR9:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,-v9.5a" }
// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+sb,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+neon,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" }
// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,-v9.5a" }
// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR19:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+jsconv,+neon,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR20:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+jsconv,+neon,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fullfp16,+neon,+rdm,+sme,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm,-v9.5a" }
// CHECK: attributes #[[ATTR19:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" }
// CHECK: attributes #[[ATTR20:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm,-v9.5a" }
// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" }
// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fp-armv8,+fullfp16,+neon,+sve,-v9.5a" }
// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fp-armv8,+fullfp16,+neon,+rdm,+sme,-v9.5a" }
// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fp-armv8,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve,-v9.5a" }
// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fp-armv8,+fullfp16,+neon,+sve,-v9.5a" }
// CHECK: attributes #[[ATTR26]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+rcpc,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+jsconv,+neon,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+fp-armv8,+jsconv,+neon,-v9.5a" }
// CHECK: attributes #[[ATTR28]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+rcpc,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+fullfp16,+neon,+sve,-v9.5a" }
// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3,-v9.5a" }
// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm,-v9.5a" }
// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4,-v9.5a" }
// CHECK: attributes #[[ATTR33]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,+mte,+rcpc,+rcpc3,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR34]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+sm4,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR35]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+rdm,-fp-armv8,-v9.5a" }
// CHECK: attributes #[[ATTR34]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sm4,-v9.5a" }
// CHECK: attributes #[[ATTR35]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon,+rdm,-v9.5a" }
//.
// CHECK-NOFMV: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
// CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,5 +221,5 @@ void tu2(int &i) {
}
}

// CHECK: [[BW_LIKELY]] = !{!"branch_weights", i32 2000, i32 1}
// CHECK: [[BW_UNLIKELY]] = !{!"branch_weights", i32 1, i32 2000}
// CHECK: [[BW_LIKELY]] = !{!"branch_weights", !"expected", i32 2000, i32 1}
// CHECK: [[BW_UNLIKELY]] = !{!"branch_weights", !"expected", i32 1, i32 2000}
4 changes: 4 additions & 0 deletions clang/test/Driver/aarch64-mcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
// CORTEXX3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-x3"
// RUN: %clang --target=aarch64 -mcpu=cortex-x4 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-X4 %s
// CORTEX-X4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-x4"
// RUN: %clang --target=aarch64 -mcpu=cortex-x925 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-X925 %s
// CORTEX-X925: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-x925"
// RUN: %clang --target=aarch64 -mcpu=cortex-a78 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEXA78 %s
// CORTEXA78: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a78"
// RUN: %clang --target=aarch64 -mcpu=cortex-a78c -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A78C %s
Expand All @@ -58,6 +60,8 @@
// CORTEX-A720: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a720"
// RUN: %clang --target=aarch64 -mcpu=cortex-a720ae -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A720AE %s
// CORTEX-A720AE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a720ae"
// RUN: %clang --target=aarch64 -mcpu=cortex-a725 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A725 %s
// CORTEX-A725: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a725"
// RUN: %clang --target=aarch64 -mcpu=neoverse-e1 -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-E1 %s
// NEOVERSE-E1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "neoverse-e1"
// RUN: %clang --target=aarch64 -mcpu=neoverse-v1 -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-V1 %s
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Driver/warning-options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
// Check that -isysroot warns on nonexistent paths.
// RUN: %clang -### -c -target i386-apple-darwin10 -isysroot %t/warning-options %s 2>&1 | FileCheck --check-prefix=CHECK-ISYSROOT %s
// CHECK-ISYSROOT: warning: no such sysroot directory: '{{.*}}/warning-options'

// Check for proper warning with -Wmissing-include-dirs
// RUN: %clang -### -Wmissing-include-dirs -I %t/warning-options %s 2>&1 | FileCheck --check-prefix=CHECK-MISSING-INCLUDE-DIRS %s
// CHECK-MISSING-INCLUDE-DIRS: warning: no such include directory: '{{.*}}/warning-options'
4 changes: 2 additions & 2 deletions clang/test/Misc/target-invalid-cpu-note.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

// RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64
// AARCH64: error: unknown target CPU 'not-a-cpu'
// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-n3, neoverse-512tvb, neoverse-v1, neoverse-v2, neoverse-v3, neoverse-v3ae, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, oryon-1, cobalt-100, grace{{$}}
// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-a725, cortex-r82, cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, cortex-x925, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-n3, neoverse-512tvb, neoverse-v1, neoverse-v2, neoverse-v3, neoverse-v3ae, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, oryon-1, cobalt-100, grace{{$}}

// RUN: not %clang_cc1 -triple arm64--- -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE_AARCH64
// TUNE_AARCH64: error: unknown target CPU 'not-a-cpu'
// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-n3, neoverse-512tvb, neoverse-v1, neoverse-v2, neoverse-v3, neoverse-v3ae, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, oryon-1, cobalt-100, grace{{$}}
// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-a725, cortex-r82, cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, cortex-x925, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-n3, neoverse-512tvb, neoverse-v1, neoverse-v2, neoverse-v3, neoverse-v3ae, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, oryon-1, cobalt-100, grace{{$}}

// RUN: not %clang_cc1 -triple i386--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86
// X86: error: unknown target CPU 'not-a-cpu'
Expand Down
36 changes: 36 additions & 0 deletions clang/test/Preprocessor/riscv-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@
// CHECK-NOT: __riscv_shvstvala {{.*$}}
// CHECK-NOT: __riscv_shvstvecd {{.*$}}
// CHECK-NOT: __riscv_smaia {{.*$}}
// CHECK-NOT: __riscv_smcdeleg {{.*$}}
// CHECK-NOT: __riscv_smcsrind {{.*$}}
// CHECK-NOT: __riscv_smepmp {{.*$}}
// CHECK-NOT: __riscv_smstateen {{.*$}}
// CHECK-NOT: __riscv_ssaia {{.*$}}
// CHECK-NOT: __riscv_ssccfg {{.*$}}
// CHECK-NOT: __riscv_ssccptr {{.*$}}
// CHECK-NOT: __riscv_sscofpmf {{.*$}}
// CHECK-NOT: __riscv_sscounterenw {{.*$}}
// CHECK-NOT: __riscv_sscsrind {{.*$}}
// CHECK-NOT: __riscv_ssstateen {{.*$}}
// CHECK-NOT: __riscv_ssstrict {{.*$}}
// CHECK-NOT: __riscv_sstc {{.*$}}
Expand Down Expand Up @@ -362,6 +366,14 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-SHVSTVECD-EXT %s
// CHECK-SHVSTVECD-EXT: __riscv_shvstvecd 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32issccfg -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCCFG-EXT %s
// RUN: %clang --target=riscv64-unknown-linux-gnu \
// RUN: -march=rv64issccfg -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCCFG-EXT %s
// CHECK-SSCCFG-EXT: __riscv_ssccfg 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32issccptr -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCCPTR-EXT %s
Expand Down Expand Up @@ -1393,6 +1405,30 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-SSAIA-EXT %s
// CHECK-SSAIA-EXT: __riscv_ssaia 1000000{{$}}

// RUN: %clang --target=riscv32 \
// RUN: -march=rv32ismcsrind1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SMCSRIND-EXT %s
// RUN: %clang --target=riscv64 \
// RUN: -march=rv64ismcsrind1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SMCSRIND-EXT %s
// CHECK-SMCSRIND-EXT: __riscv_smcsrind 1000000{{$}}

// RUN: %clang --target=riscv32 \
// RUN: -march=rv32isscsrind1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCSRIND-EXT %s
// RUN: %clang --target=riscv64 \
// RUN: -march=rv64isscsrind1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCSRIND-EXT %s
// CHECK-SSCSRIND-EXT: __riscv_sscsrind 1000000{{$}}

// RUN: %clang --target=riscv32 \
// RUN: -march=rv32ismcdeleg1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SMCDELEG-EXT %s
// RUN: %clang --target=riscv64 \
// RUN: -march=rv64ismcdeleg1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SMCDELEG-EXT %s
// CHECK-SMCDELEG-EXT: __riscv_smcdeleg 1000000{{$}}

// RUN: %clang --target=riscv32 \
// RUN: -march=rv32ismepmp1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SMEPMP-EXT %s
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Sema/aarch64-neon-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ void undefined(uint32x2_t v2i32, uint32x4_t v4i32, uint16x8_t v8i16, uint8x16_t
vrnd_f16(v4f16); // expected-error {{always_inline function 'vrnd_f16' requires target feature 'fullfp16'}}
vmaxnm_f16(v4f16, v4f16); // expected-error {{always_inline function 'vmaxnm_f16' requires target feature 'fullfp16'}}
vrndi_f16(v4f16); // expected-error {{always_inline function 'vrndi_f16' requires target feature 'fullfp16'}}
// fp16fml
vfmlal_low_f16(v2f32, v4f16, v4f16); // expected-error {{always_inline function 'vfmlal_low_f16' requires target feature 'fp16fml'}}
// fp16fml depends on fp-armv8
vfmlal_low_f16(v2f32, v4f16, v4f16); // expected-error {{always_inline function 'vfmlal_low_f16' requires target feature 'fp-armv8'}}
// i8mm
vmmlaq_s32(v4i32, v8i16, v8i16); // expected-error {{always_inline function 'vmmlaq_s32' requires target feature 'i8mm'}}
vusdot_laneq_s32(v2i32, v8i8, v8i16, 0); // expected-error {{always_inline function 'vusdot_s32' requires target feature 'i8mm'}}
Expand Down
3 changes: 1 addition & 2 deletions clang/tools/driver/cc1as_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
MCOptions.MCRelaxAll = Opts.RelaxAll;
MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical;
MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels;
MCOptions.X86RelaxRelocations = Opts.RelaxELFRelocations;
MCOptions.CompressDebugSections = Opts.CompressDebugSections;
MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
Expand Down Expand Up @@ -483,8 +484,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
MOFI->setDarwinTargetVariantSDKVersion(Opts.DarwinTargetVariantSDKVersion);
Ctx.setObjectFileInfo(MOFI.get());

if (Opts.SaveTemporaryLabels)
Ctx.setAllowTemporaryLabels(false);
if (Opts.GenDwarfForAssembly)
Ctx.setGenDwarfForAssembly(true);
if (!Opts.DwarfDebugFlags.empty())
Expand Down
1 change: 1 addition & 0 deletions clang/unittests/AST/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_clang_unittest(ASTTests
EvaluateAsRValueTest.cpp
ExternalASTSourceTest.cpp
NamedDeclPrinterTest.cpp
ProfilingTest.cpp
RandstructTest.cpp
RecursiveASTVisitorTest.cpp
SizelessTypesTest.cpp
Expand Down
73 changes: 73 additions & 0 deletions clang/unittests/AST/ProfilingTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//===- unittests/AST/ProfilingTest.cpp --- Tests for Profiling ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
#include <utility>

namespace clang {
namespace {
using namespace ast_matchers;

static auto getClassTemplateRedecls() {
std::string Code = R"cpp(
template <class> struct A;
template <class> struct A;
template <class> struct A;
)cpp";
auto AST = tooling::buildASTFromCode(Code);
ASTContext &Ctx = AST->getASTContext();

auto MatchResults = match(classTemplateDecl().bind("id"), Ctx);
SmallVector<ClassTemplateDecl *, 3> Res;
for (BoundNodes &N : MatchResults) {
if (auto *CTD = const_cast<ClassTemplateDecl *>(
N.getNodeAs<ClassTemplateDecl>("id")))
Res.push_back(CTD);
}
assert(Res.size() == 3);
for (auto &&I : Res)
assert(I->getCanonicalDecl() == Res[0]);
return std::make_tuple(std::move(AST), Res[1], Res[2]);
}

template <class T> static void testTypeNode(const T *T1, const T *T2) {
{
llvm::FoldingSetNodeID ID1, ID2;
T1->Profile(ID1);
T2->Profile(ID2);
ASSERT_NE(ID1, ID2);
}
auto *CT1 = cast<T>(T1->getCanonicalTypeInternal());
auto *CT2 = cast<T>(T2->getCanonicalTypeInternal());
{
llvm::FoldingSetNodeID ID1, ID2;
CT1->Profile(ID1);
CT2->Profile(ID2);
ASSERT_EQ(ID1, ID2);
}
}

TEST(Profiling, DeducedTemplateSpecializationType_Name) {
auto [AST, CTD1, CTD2] = getClassTemplateRedecls();
ASTContext &Ctx = AST->getASTContext();

auto *T1 = cast<DeducedTemplateSpecializationType>(
Ctx.getDeducedTemplateSpecializationType(TemplateName(CTD1), QualType(),
false));
auto *T2 = cast<DeducedTemplateSpecializationType>(
Ctx.getDeducedTemplateSpecializationType(TemplateName(CTD2), QualType(),
false));
testTypeNode(T1, T2);
}

} // namespace
} // namespace clang
57 changes: 55 additions & 2 deletions clang/unittests/AST/StructuralEquivalenceTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1877,6 +1877,34 @@ TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) {
EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));
}

TEST_F(StructuralEquivalenceCacheTest,
NonTypeTemplateParmWithDifferentPositionNoEq) {
auto TU = makeTuDecls(
R"(
template<int T>
struct A {
template<int U>
void foo() {}
};
)",
R"(
template<int U>
struct A {
template<int V, int T>
void foo() {}
};
)",
Lang_CXX03);

StructuralEquivalenceContext Ctx(
get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);

auto NTTP = findDeclPair<NonTypeTemplateParmDecl>(
TU, nonTypeTemplateParmDecl(hasName("T")));
EXPECT_FALSE(Ctx.IsEquivalent(NTTP.first, NTTP.second));
}

TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) {
auto TU = makeTuDecls(
R"(
Expand Down Expand Up @@ -2441,8 +2469,7 @@ TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) {
void foo(A<T, y>);
)",
Lang_CXX11);
// FIXME: These should not match,
EXPECT_TRUE(testStructuralMatch(t));
EXPECT_FALSE(testStructuralMatch(t));
}

TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) {
Expand Down Expand Up @@ -2595,5 +2622,31 @@ TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) {
EXPECT_FALSE(testStructuralMatch(t));
}

TEST_F(StructuralEquivalenceCacheTest, CXXDependentScopeMemberExprNoEq) {
auto S = makeStmts(
R"(
template <class T>
void foo() {
(void)T().x;
}
struct A { int x; };
void bar() {
foo<A>();
}
)",
R"(
template <class T>
void foo() {
(void)T().y;
}
struct A { int y; };
void bar() {
foo<A>();
}
)",
Lang_CXX11, cxxDependentScopeMemberExpr());
EXPECT_FALSE(testStructuralMatch(S));
}

} // end namespace ast_matchers
} // end namespace clang
6 changes: 6 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1655,6 +1655,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
EXPECT_TOKEN(Tokens[2], tok::arrow, TT_TrailingReturnArrow);
EXPECT_TOKEN(Tokens[4], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("[] -> struct S { return {}; }");
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[2], tok::arrow, TT_TrailingReturnArrow);
EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace);

Tokens = annotate("foo([&](u32 bar) __attribute__((attr)) -> void {});");
ASSERT_EQ(Tokens.size(), 22u) << Tokens;
EXPECT_TOKEN(Tokens[2], tok::l_square, TT_LambdaLSquare);
Expand Down
16 changes: 0 additions & 16 deletions clang/www/analyzer/alpha_checks.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,22 +239,6 @@ <h3 id="core_alpha_checkers">Core Alpha Checkers</h3>
</pre></div></div></td></tr>


<tr><td><a id="alpha.core.SizeofPtr"><div class="namedescr expandable"><span class="name">
alpha.core.SizeofPtr</span><span class="lang">
(C)</span><div class="descr">
Warn about unintended use of <code>sizeof()</code> on pointer
expressions.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
struct s {};

int test(struct s *p) {
return sizeof(p);
// warn: sizeof(ptr) can produce an unexpected result
}
</pre></div></div></td></tr>


<tr><td><a id="alpha.core.StackAddressAsyncEscape"><div class="namedescr expandable"><span class="name">
alpha.core.StackAddressAsyncEscape</span><span class="lang">
(C)</span><div class="descr">
Expand Down
23 changes: 17 additions & 6 deletions compiler-rt/lib/builtins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -561,12 +561,23 @@ set(aarch64_SOURCES
aarch64/fp_mode.c
)

if(COMPILER_RT_HAS_AARCH64_SME AND COMPILER_RT_HAS_FNO_BUILTIN_FLAG AND (COMPILER_RT_HAS_AUXV OR COMPILER_RT_BAREMETAL_BUILD))
list(APPEND aarch64_SOURCES aarch64/sme-abi.S aarch64/sme-abi-init.c aarch64/sme-abi-vg.c aarch64/sme-libc-routines.c)
message(STATUS "AArch64 SME ABI routines enabled")
set_source_files_properties(aarch64/sme-libc-routines.c PROPERTIES COMPILE_FLAGS "-fno-builtin")
else()
message(STATUS "AArch64 SME ABI routines disabled")
if (COMPILER_RT_HAS_AARCH64_SME)
if (NOT COMPILER_RT_DISABLE_AARCH64_FMV AND COMPILER_RT_HAS_FNO_BUILTIN_FLAG AND (COMPILER_RT_HAS_AUXV OR COMPILER_RT_BAREMETAL_BUILD))
list(APPEND aarch64_SOURCES aarch64/sme-abi.S aarch64/sme-abi-init.c aarch64/sme-abi-vg.c aarch64/sme-libc-routines.c)
message(STATUS "AArch64 SME ABI routines enabled")
set_source_files_properties(aarch64/sme-libc-routines.c PROPERTIES COMPILE_FLAGS "-fno-builtin")
else()
if(COMPILER_RT_DISABLE_AARCH64_FMV)
message(WARNING "AArch64 SME ABI routines require function multiversioning support.")
endif()
if(NOT COMPILER_RT_HAS_FNO_BUILTIN_FLAG)
message(WARNING "AArch64 SME ABI routines require '-fno-builtin'")
endif()
if(NOT (COMPILER_RT_HAS_AUXV OR COMPILER_RT_BAREMETAL_BUILD))
message(WARNING "AArch64 SME ABI routines requires sys/auxv.h or COMPILER_RT_BAREMETAL_BUILD flag")
endif()
message(STATUS "AArch64 SME ABI routines disabled")
endif()
endif()

# Generate outline atomics helpers from lse.S base
Expand Down
6 changes: 3 additions & 3 deletions compiler-rt/test/asan/TestCases/Linux/stack-trace-dlclose.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ int main(int argc, char **argv) {
}
#endif

// CHECK: {{ #0 0x.* in (__interceptor_)?malloc}}
// CHECK: {{ #1 0x.* \(<unknown module>\)}}
// CHECK: {{ #2 0x.* in main}}
// CHECK: {{ #[0-9]+ 0x.* in (__interceptor_)?malloc}}
// CHECK: {{ #[0-9]+ 0x.* \(<unknown module>\)}}
// CHECK: {{ #[0-9]+ 0x.* in main}}
4 changes: 2 additions & 2 deletions compiler-rt/test/asan/TestCases/Posix/strndup_oob_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ int main(int argc, char **argv) {
char *copy = strndup(kString, 2);
int x = copy[2 + argc]; // BOOM
// CHECK: AddressSanitizer: heap-buffer-overflow
// CHECK: #0 {{.*}}main {{.*}}strndup_oob_test.cpp:[[@LINE-2]]
// CHECK: #{{[0-9]+}} {{.*}}main {{.*}}strndup_oob_test.cpp:[[@LINE-2]]
// CHECK-LABEL: allocated by thread T{{.*}} here:
// CHECK: #{{[01]}} {{.*}}strndup
// CHECK: #{{[0-9]+}} {{.*}}strndup
// CHECK: #{{.*}}main {{.*}}strndup_oob_test.cpp:[[@LINE-6]]
// CHECK-LABEL: SUMMARY
// CHECK: strndup_oob_test.cpp:[[@LINE-7]]
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/test/asan/TestCases/calloc-overflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
int main() {
void *p = calloc(-1, 1000);
// CHECK: {{ERROR: AddressSanitizer: calloc parameters overflow: count \* size \(.* \* 1000\) cannot be represented in type size_t}}
// CHECK: {{#0 0x.* in .*calloc}}
// CHECK: {{#[1-3] 0x.* in main .*calloc-overflow.cpp:}}[[@LINE-3]]
// CHECK: {{#[0-9]+ 0x.* in calloc .*.cpp}}
// CHECK: {{#[0-9]+ 0x.* in main .*calloc-overflow.cpp:}}[[@LINE-3]]
// CHECK: SUMMARY: AddressSanitizer: calloc-overflow

printf("calloc returned: %zu\n", (size_t)p);
Expand Down
8 changes: 4 additions & 4 deletions compiler-rt/test/asan/TestCases/debug_stacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ int main() {
// CHECK: ERROR: AddressSanitizer: heap-use-after-free
// CHECK: WRITE of size 1 at 0x{{.*}}
// CHECK: freed by thread T0 here:
// CHECK: #0 [[FREE_FRAME_0]]
// CHECK: #1 [[FREE_FRAME_1]]
// CHECK: #{{[0-9]+}} [[FREE_FRAME_0]]
// CHECK: #{{[0-9]+}} [[FREE_FRAME_1]]
// CHECK: previously allocated by thread T0 here:
// CHECK: #0 [[ALLOC_FRAME_0]]
// CHECK: #1 [[ALLOC_FRAME_1]]
// CHECK: #{{[0-9+]}} [[ALLOC_FRAME_0]]
// CHECK: #{{[0-9+]}} [[ALLOC_FRAME_1]]

return 0;
}
6 changes: 3 additions & 3 deletions compiler-rt/test/asan/TestCases/double-free.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ int main(int argc, char **argv) {
free(x);
free(x + argc - 1); // BOOM
// CHECK: AddressSanitizer: attempting double-free{{.*}}in thread T0
// CHECK: #0 0x{{.*}} in {{.*}}free
// CHECK: #{{[1-3]}} 0x{{.*}} in main {{.*}}double-free.cpp:[[@LINE-3]]
// CHECK: #{{[0-9]+}} 0x{{.*}} in {{.*}}free
// CHECK: #{{[0-9]+}} 0x{{.*}} in main {{.*}}double-free.cpp:[[@LINE-3]]
// CHECK: freed by thread T0 here:
// MALLOC-CTX: #0 0x{{.*}} in {{.*}}free
// MALLOC-CTX: #{{[1-3]}} 0x{{.*}} in main {{.*}}double-free.cpp:[[@LINE-7]]
// MALLOC-CTX: #{{[0-9]+}} 0x{{.*}} in main {{.*}}double-free.cpp:[[@LINE-7]]
// CHECK: allocated by thread T0 here:
// MALLOC-CTX: double-free.cpp:[[@LINE-12]]
// CHECK-RECOVER: AddressSanitizer: attempting double-free{{.*}}in thread T0
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/test/asan/TestCases/malloc-size-too-big.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ static const size_t kMaxAllowedMallocSizePlusOne =
int main() {
void *p = malloc(kMaxAllowedMallocSizePlusOne);
// CHECK: {{ERROR: AddressSanitizer: requested allocation size .* \(.* after adjustments for alignment, red zones etc\.\) exceeds maximum supported size}}
// CHECK: {{#0 0x.* in .*malloc}}
// CHECK: {{#[1-3] 0x.* in main .*malloc-size-too-big.cpp:}}[[@LINE-3]]
// CHECK: {{#[0-9] 0x.* in .*malloc}}
// CHECK: {{#[0-9] 0x.* in main .*malloc-size-too-big.cpp:}}[[@LINE-3]]
// CHECK: SUMMARY: AddressSanitizer: allocation-size-too-big

printf("malloc returned: %zu\n", (size_t)p);
Expand Down
6 changes: 3 additions & 3 deletions compiler-rt/test/asan/TestCases/strcpy-overlap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ __attribute__((noinline)) void bad_function() {
char buffer[] = "hello";
// CHECK: strcpy-param-overlap: memory ranges
// CHECK: [{{0x.*,[ ]*0x.*}}) and [{{0x.*,[ ]*0x.*}}) overlap
// CHECK: {{#0 0x.* in .*strcpy}}
// CHECK: {{#1 0x.* in bad_function.*strcpy-overlap.cpp:}}[[@LINE+2]]
// CHECK: {{#2 0x.* in main .*strcpy-overlap.cpp:}}[[@LINE+5]]
// CHECK: {{#[0-9]+ 0x.* in .*strcpy.* .*.cpp}}
// CHECK: {{#[0-9]+ 0x.* in bad_function.*strcpy-overlap.cpp:}}[[@LINE+2]]
// CHECK: {{#[0-9]+ 0x.* in main .*strcpy-overlap.cpp:}}[[@LINE+5]]
strcpy(buffer, buffer + 1); // BOOM
}

Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/asan/TestCases/strdup_oob_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ int main(int argc, char **argv) {
// CHECK: AddressSanitizer: heap-buffer-overflow
// CHECK: #0 {{.*}}main {{.*}}strdup_oob_test.cpp:[[@LINE-2]]
// CHECK-LABEL: allocated by thread T{{.*}} here:
// CHECK: #{{[01]}} {{.*}}strdup
// CHECK: #{{[0-9]+}} {{.*}}strdup
// CHECK: #{{.*}}main {{.*}}strdup_oob_test.cpp:[[@LINE-6]]
// CHECK-LABEL: SUMMARY
// CHECK: strdup_oob_test.cpp:[[@LINE-7]]
Expand Down
8 changes: 4 additions & 4 deletions compiler-rt/test/asan/TestCases/strncpy-overflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ int main(int argc, char **argv) {
char *short_buffer = (char*)malloc(9);
strncpy(short_buffer, hello, 10); // BOOM
// CHECK: {{WRITE of size 10 at 0x.* thread T0}}
// CHECK: {{ #0 0x.* in .*strncpy}}
// CHECK: {{ #1 0x.* in main .*strncpy-overflow.cpp:}}[[@LINE-3]]
// CHECK: {{ #[0-9]+ 0x.* in .*strncpy .*.cpp}}
// CHECK: {{ #[0-9]+ 0x.* in main .*strncpy-overflow.cpp:}}[[@LINE-3]]
// CHECK: {{0x.* is located 0 bytes after 9-byte region}}
// CHECK: {{allocated by thread T0 here:}}
// CHECK: {{ #0 0x.* in .*malloc}}
// CHECK: {{ #[1-3] 0x.* in main .*strncpy-overflow.cpp:}}[[@LINE-8]]
// CHECK: {{ #[0-9]+ 0x.* in .*malloc}}
// CHECK: {{ #[0-9]+ 0x.* in main .*strncpy-overflow.cpp:}}[[@LINE-8]]
return rval + sink_memory(9, short_buffer);
}
10 changes: 5 additions & 5 deletions compiler-rt/test/asan/TestCases/use-after-free-right.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ int main() {
// CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
// CHECK: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
// CHECK: {{WRITE of size 1 at 0x.* thread T0}}
// CHECK: {{ #0 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-4]]
// CHECK: {{ #[0-9]+ 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-4]]
// CHECK: {{0x.* is located 0 bytes inside of 1-byte region .0x.*,0x.*}}
// CHECK: {{freed by thread T0 here:}}
// CHECK: {{ #0 0x.* in .*free}}
// CHECK: {{ #[1-3] 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-9]]
// CHECK: {{ #[0-9]+ 0x.* in .*free.* .*.cpp}}
// CHECK: {{ #[0-9]+ 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-9]]

// CHECK: {{previously allocated by thread T0 here:}}
// CHECK: {{ #0 0x.* in .*malloc}}
// CHECK: {{ #[1-3] 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-14]]
// CHECK: {{ #[0-9]+ 0x.* in .*malloc}}
// CHECK: {{ #[0-9]+ 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-14]]
}
10 changes: 5 additions & 5 deletions compiler-rt/test/asan/TestCases/use-after-free.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ int main() {
// CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
// CHECK: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
// CHECK: {{READ of size 1 at 0x.* thread T0}}
// CHECK: {{ #0 0x.* in main .*use-after-free.cpp:}}[[@LINE-4]]
// CHECK: {{ #[0-9]+ 0x.* in main .*use-after-free.cpp:}}[[@LINE-4]]
// CHECK: {{0x.* is located 5 bytes inside of 10-byte region .0x.*,0x.*}}
// CHECK: {{freed by thread T0 here:}}
// CHECK: {{ #0 0x.* in .*free}}
// CHECK: {{ #[1-3] 0x.* in main .*use-after-free.cpp:}}[[@LINE-9]]
// CHECK: {{ #[0-9]+ 0x.* in .*free}}
// CHECK: {{ #[0-9]+ 0x.* in main .*use-after-free.cpp:}}[[@LINE-9]]

// CHECK: {{previously allocated by thread T0 here:}}
// CHECK: {{ #0 0x.* in .*malloc}}
// CHECK: {{ #[1-3] 0x.* in main .*use-after-free.cpp:}}[[@LINE-14]]
// CHECK: {{ #[0-9]+ 0x.* in .*malloc}}
// CHECK: {{ #[0-9]+ 0x.* in main .*use-after-free.cpp:}}[[@LINE-14]]
// CHECK: Shadow byte legend (one shadow byte represents {{[0-9]+}} application bytes):
// CHECK: Global redzone:
// CHECK: ASan internal:
Expand Down
17 changes: 10 additions & 7 deletions flang/include/flang/Lower/PFTBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@

namespace Fortran::lower::pft {

struct CompilerDirectiveUnit;
struct Evaluation;
struct Program;
struct ModuleLikeUnit;
struct FunctionLikeUnit;
struct ModuleLikeUnit;
struct Program;

using ContainedUnit = std::variant<CompilerDirectiveUnit, FunctionLikeUnit>;
using ContainedUnitList = std::list<ContainedUnit>;
using EvaluationList = std::list<Evaluation>;

/// Provide a variant like container that can hold references. It can hold
Expand Down Expand Up @@ -594,8 +597,8 @@ VariableList getDependentVariableList(const Fortran::semantics::Symbol &);

void dump(VariableList &, std::string s = {}); // `s` is an optional dump label

/// Function-like units may contain evaluations (executable statements) and
/// nested function-like units (internal procedures and function statements).
/// Function-like units may contain evaluations (executable statements),
/// directives, and internal (nested) function-like units.
struct FunctionLikeUnit : public ProgramUnit {
// wrapper statements for function-like syntactic structures
using FunctionStatement =
Expand Down Expand Up @@ -697,10 +700,10 @@ struct FunctionLikeUnit : public ProgramUnit {
std::optional<FunctionStatement> beginStmt;
FunctionStatement endStmt;
const semantics::Scope *scope;
EvaluationList evaluationList;
LabelEvalMap labelEvaluationMap;
SymbolLabelMap assignSymbolLabelMap;
std::list<FunctionLikeUnit> nestedFunctions;
ContainedUnitList containedUnitList;
EvaluationList evaluationList;
/// <Symbol, Evaluation> pairs for each entry point. The pair at index 0
/// is the primary entry point; remaining pairs are alternate entry points.
/// The primary entry point symbol is Null for an anonymous program.
Expand Down Expand Up @@ -746,7 +749,7 @@ struct ModuleLikeUnit : public ProgramUnit {

ModuleStatement beginStmt;
ModuleStatement endStmt;
std::list<FunctionLikeUnit> nestedFunctions;
ContainedUnitList containedUnitList;
EvaluationList evaluationList;
};

Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Lower/Support/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ class IsEqualEvaluateExpr {
return std::visit(
[&](const auto &p, const auto &q) { return isEqual(p, q); },
x.parent(), y.parent()) &&
isEqual(x.lower(), y.lower()) && isEqual(x.lower(), y.lower());
isEqual(x.lower(), y.lower()) && isEqual(x.upper(), y.upper());
}
static bool isEqual(const Fortran::evaluate::StaticDataObject::Pointer &x,
const Fortran::evaluate::StaticDataObject::Pointer &y) {
Expand Down
23 changes: 22 additions & 1 deletion flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
include "flang/Optimizer/Dialect/CUF/CUFDialect.td"
include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.td"
include "flang/Optimizer/Dialect/FIRTypes.td"
include "flang/Optimizer/Dialect/FIRAttr.td"
include "mlir/Interfaces/LoopLikeInterface.td"
include "mlir/IR/BuiltinAttributes.td"

Expand Down Expand Up @@ -249,7 +250,9 @@ def cuf_KernelOp : cuf_Op<"kernel", [AttrSizedOperandSegments,
Variadic<Index>:$lowerbound,
Variadic<Index>:$upperbound,
Variadic<Index>:$step,
OptionalAttr<I64Attr>:$n
OptionalAttr<I64Attr>:$n,
Variadic<AnyType>:$reduceOperands,
OptionalAttr<ArrayAttr>:$reduceAttrs
);

let regions = (region AnyRegion:$region);
Expand All @@ -258,11 +261,29 @@ def cuf_KernelOp : cuf_Op<"kernel", [AttrSizedOperandSegments,
`<` `<` `<` custom<CUFKernelValues>($grid, type($grid)) `,`
custom<CUFKernelValues>($block, type($block))
( `,` `stream` `=` $stream^ )? `>` `>` `>`
( `reduce` `(` $reduceOperands^ `:` type($reduceOperands) `:` $reduceAttrs `)` )?
custom<CUFKernelLoopControl>($region, $lowerbound, type($lowerbound),
$upperbound, type($upperbound), $step, type($step))
attr-dict
}];

let extraClassDeclaration = [{
/// Get Number of variadic operands
unsigned getNumOperands(unsigned idx) {
auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
getOperandSegmentSizeAttr());
return static_cast<unsigned>(segments[idx]);
}
// Get Number of reduction operands
unsigned getNumReduceOperands() {
return getNumOperands(7);
}
/// Does the operation hold operands for reduction variables
bool hasReduceOperands() {
return getNumReduceOperands() > 0;
}
}];

let hasVerifier = 1;
}

Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Parser/token-sequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class TokenSequence {
TokenSequence &RemoveRedundantBlanks(std::size_t firstChar = 0);
TokenSequence &ClipComment(const Prescanner &, bool skipFirst = false);
const TokenSequence &CheckBadFortranCharacters(
Messages &, const Prescanner &) const;
Messages &, const Prescanner &, bool allowAmpersand) const;
const TokenSequence &CheckBadParentheses(Messages &) const;
void Emit(CookedSource &) const;
llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
Expand Down
102 changes: 70 additions & 32 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,28 +302,32 @@ class FirConverter : public Fortran::lower::AbstractConverter {
bool hasMainProgram = false;
const Fortran::semantics::Symbol *globalOmpRequiresSymbol = nullptr;
for (Fortran::lower::pft::Program::Units &u : pft.getUnits()) {
std::visit(Fortran::common::visitors{
[&](Fortran::lower::pft::FunctionLikeUnit &f) {
if (f.isMainProgram())
hasMainProgram = true;
declareFunction(f);
if (!globalOmpRequiresSymbol)
globalOmpRequiresSymbol = f.getScope().symbol();
},
[&](Fortran::lower::pft::ModuleLikeUnit &m) {
lowerModuleDeclScope(m);
for (Fortran::lower::pft::FunctionLikeUnit &f :
m.nestedFunctions)
declareFunction(f);
},
[&](Fortran::lower::pft::BlockDataUnit &b) {
if (!globalOmpRequiresSymbol)
globalOmpRequiresSymbol = b.symTab.symbol();
},
[&](Fortran::lower::pft::CompilerDirectiveUnit &d) {},
[&](Fortran::lower::pft::OpenACCDirectiveUnit &d) {},
},
u);
std::visit(
Fortran::common::visitors{
[&](Fortran::lower::pft::FunctionLikeUnit &f) {
if (f.isMainProgram())
hasMainProgram = true;
declareFunction(f);
if (!globalOmpRequiresSymbol)
globalOmpRequiresSymbol = f.getScope().symbol();
},
[&](Fortran::lower::pft::ModuleLikeUnit &m) {
lowerModuleDeclScope(m);
for (Fortran::lower::pft::ContainedUnit &unit :
m.containedUnitList)
if (auto *f =
std::get_if<Fortran::lower::pft::FunctionLikeUnit>(
&unit))
declareFunction(*f);
},
[&](Fortran::lower::pft::BlockDataUnit &b) {
if (!globalOmpRequiresSymbol)
globalOmpRequiresSymbol = b.symTab.symbol();
},
[&](Fortran::lower::pft::CompilerDirectiveUnit &d) {},
[&](Fortran::lower::pft::OpenACCDirectiveUnit &d) {},
},
u);
}

// Create definitions of intrinsic module constants.
Expand Down Expand Up @@ -387,13 +391,15 @@ class FirConverter : public Fortran::lower::AbstractConverter {

// Compute the set of host associated entities from the nested functions.
llvm::SetVector<const Fortran::semantics::Symbol *> escapeHost;
for (Fortran::lower::pft::FunctionLikeUnit &f : funit.nestedFunctions)
collectHostAssociatedVariables(f, escapeHost);
for (Fortran::lower::pft::ContainedUnit &unit : funit.containedUnitList)
if (auto *f = std::get_if<Fortran::lower::pft::FunctionLikeUnit>(&unit))
collectHostAssociatedVariables(*f, escapeHost);
funit.setHostAssociatedSymbols(escapeHost);

// Declare internal procedures
for (Fortran::lower::pft::FunctionLikeUnit &f : funit.nestedFunctions)
declareFunction(f);
for (Fortran::lower::pft::ContainedUnit &unit : funit.containedUnitList)
if (auto *f = std::get_if<Fortran::lower::pft::FunctionLikeUnit>(&unit))
declareFunction(*f);
}

/// Get the scope that is defining or using \p sym. The returned scope is not
Expand Down Expand Up @@ -2669,6 +2675,35 @@ class FirConverter : public Fortran::lower::AbstractConverter {
std::get<2>(dir.t);
const std::optional<Fortran::parser::ScalarIntExpr> &stream =
std::get<3>(dir.t);
const std::list<Fortran::parser::CUFReduction> &cufreds =
std::get<4>(dir.t);

llvm::SmallVector<mlir::Value> reduceOperands;
llvm::SmallVector<mlir::Attribute> reduceAttrs;

for (const Fortran::parser::CUFReduction &cufred : cufreds) {
fir::ReduceOperationEnum redOpEnum = getReduceOperationEnum(
std::get<Fortran::parser::ReductionOperator>(cufred.t));
const std::list<Fortran::parser::Scalar<Fortran::parser::Variable>>
&scalarvars = std::get<1>(cufred.t);
for (const Fortran::parser::Scalar<Fortran::parser::Variable> &scalarvar :
scalarvars) {
auto reduce_attr =
fir::ReduceAttr::get(builder->getContext(), redOpEnum);
reduceAttrs.push_back(reduce_attr);
const Fortran::parser::Variable &var = scalarvar.thing;
if (const auto *iDesignator = std::get_if<
Fortran::common::Indirection<Fortran::parser::Designator>>(
&var.u)) {
const Fortran::parser::Designator &designator = iDesignator->value();
if (const auto *name =
Fortran::semantics::getDesignatorNameIfDataRef(designator)) {
auto val = getSymbolAddress(*name->symbol);
reduceOperands.push_back(val);
}
}
}
}

auto isOnlyStars =
[&](const std::list<Fortran::parser::CUFKernelDoConstruct::StarOrExpr>
Expand Down Expand Up @@ -2771,8 +2806,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
loopEval = &*std::next(loopEval->getNestedEvaluations().begin());
}

auto op = builder->create<cuf::KernelOp>(loc, gridValues, blockValues,
streamValue, lbs, ubs, steps, n);
auto op = builder->create<cuf::KernelOp>(
loc, gridValues, blockValues, streamValue, lbs, ubs, steps, n,
mlir::ValueRange(reduceOperands), builder->getArrayAttr(reduceAttrs));
builder->createBlock(&op.getRegion(), op.getRegion().end(), ivTypes,
ivLocs);
mlir::Block &b = op.getRegion().back();
Expand Down Expand Up @@ -5356,8 +5392,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
endNewFunction(funit);
}
funit.setActiveEntry(0);
for (Fortran::lower::pft::FunctionLikeUnit &f : funit.nestedFunctions)
lowerFunc(f); // internal procedure
for (Fortran::lower::pft::ContainedUnit &unit : funit.containedUnitList)
if (auto *f = std::get_if<Fortran::lower::pft::FunctionLikeUnit>(&unit))
lowerFunc(*f); // internal procedure
}

/// Lower module variable definitions to fir::globalOp and OpenMP/OpenACC
Expand All @@ -5381,8 +5418,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {

/// Lower functions contained in a module.
void lowerMod(Fortran::lower::pft::ModuleLikeUnit &mod) {
for (Fortran::lower::pft::FunctionLikeUnit &f : mod.nestedFunctions)
lowerFunc(f);
for (Fortran::lower::pft::ContainedUnit &unit : mod.containedUnitList)
if (auto *f = std::get_if<Fortran::lower::pft::FunctionLikeUnit>(&unit))
lowerFunc(*f);
}

void setCurrentPosition(const Fortran::parser::CharBlock &position) {
Expand Down
14 changes: 14 additions & 0 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,20 @@ bool ClauseProcessor::processDeviceType(
return false;
}

bool ClauseProcessor::processDistSchedule(
lower::StatementContext &stmtCtx,
mlir::omp::DistScheduleClauseOps &result) const {
if (auto *clause = findUniqueClause<omp::clause::DistSchedule>()) {
result.distScheduleStaticAttr = converter.getFirOpBuilder().getUnitAttr();
const auto &chunkSize = std::get<std::optional<ExprTy>>(clause->t);
if (chunkSize)
result.distScheduleChunkSizeVar =
fir::getBase(converter.genExprValue(*chunkSize, stmtCtx));
return true;
}
return false;
}

bool ClauseProcessor::processFinal(lower::StatementContext &stmtCtx,
mlir::omp::FinalClauseOps &result) const {
const parser::CharBlock *source = nullptr;
Expand Down
2 changes: 2 additions & 0 deletions flang/lib/Lower/OpenMP/ClauseProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class ClauseProcessor {
bool processDevice(lower::StatementContext &stmtCtx,
mlir::omp::DeviceClauseOps &result) const;
bool processDeviceType(mlir::omp::DeviceTypeClauseOps &result) const;
bool processDistSchedule(lower::StatementContext &stmtCtx,
mlir::omp::DistScheduleClauseOps &result) const;
bool processFinal(lower::StatementContext &stmtCtx,
mlir::omp::FinalClauseOps &result) const;
bool processHasDeviceAddr(
Expand Down
58 changes: 56 additions & 2 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,18 @@ static void genCriticalDeclareClauses(lower::AbstractConverter &converter,
mlir::StringAttr::get(converter.getFirOpBuilder().getContext(), name);
}

static void genDistributeClauses(lower::AbstractConverter &converter,
semantics::SemanticsContext &semaCtx,
lower::StatementContext &stmtCtx,
const List<Clause> &clauses,
mlir::Location loc,
mlir::omp::DistributeClauseOps &clauseOps) {
ClauseProcessor cp(converter, semaCtx, clauses);
cp.processAllocate(clauseOps);
cp.processDistSchedule(stmtCtx, clauseOps);
// TODO Support delayed privatization.
}

static void genFlushClauses(lower::AbstractConverter &converter,
semantics::SemanticsContext &semaCtx,
const ObjectList &objects,
Expand Down Expand Up @@ -1288,8 +1300,50 @@ genDistributeOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval, mlir::Location loc,
const ConstructQueue &queue, ConstructQueue::iterator item) {
TODO(loc, "Distribute construct");
return nullptr;
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
symTable.pushScope();
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
lower::omp::isLastItemInQueue(item, queue));
dsp.processStep1();

lower::StatementContext stmtCtx;
mlir::omp::LoopNestClauseOps loopClauseOps;
mlir::omp::DistributeClauseOps distributeClauseOps;
llvm::SmallVector<const semantics::Symbol *> iv;
genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
loopClauseOps, iv);
genDistributeClauses(converter, semaCtx, stmtCtx, item->clauses, loc,
distributeClauseOps);

// Create omp.distribute wrapper.
auto distributeOp =
firOpBuilder.create<mlir::omp::DistributeOp>(loc, distributeClauseOps);

firOpBuilder.createBlock(&distributeOp.getRegion());
firOpBuilder.setInsertionPoint(
lower::genOpenMPTerminator(firOpBuilder, distributeOp, loc));

// Create nested omp.loop_nest and fill body with loop contents.
auto loopOp = firOpBuilder.create<mlir::omp::LoopNestOp>(loc, loopClauseOps);

auto *nestedEval =
getCollapsedLoopEval(eval, getCollapseValue(item->clauses));

auto ivCallback = [&](mlir::Operation *op) {
genLoopVars(op, converter, loc, iv);
return iv;
};

createBodyOfOp(*loopOp,
OpWithBodyGenInfo(converter, symTable, semaCtx, loc,
*nestedEval, llvm::omp::Directive::OMPD_simd)
.setClauses(&item->clauses)
.setDataSharingProcessor(&dsp)
.setGenRegionEntryCb(ivCallback),
queue, item);

symTable.popScope();
return distributeOp;
}

static mlir::omp::FlushOp
Expand Down
149 changes: 95 additions & 54 deletions flang/lib/Lower/PFTBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,20 @@ class PFTBuilder {
}
}

bool Pre(const parser::SpecificationPart &) {
++specificationPartLevel;
return true;
}
void Post(const parser::SpecificationPart &) { --specificationPartLevel; }

bool Pre(const parser::ContainsStmt &) {
if (!specificationPartLevel) {
assert(containsStmtStack.size() && "empty contains stack");
containsStmtStack.back() = true;
}
return false;
}

// Module like
bool Pre(const parser::Module &node) { return enterModule(node); }
bool Pre(const parser::Submodule &node) { return enterModule(node); }
Expand Down Expand Up @@ -249,15 +263,21 @@ class PFTBuilder {
whereBody.u);
}

// CompilerDirective have special handling in case they are top level
// directives (i.e. they do not belong to a ProgramUnit).
// A CompilerDirective may appear outside any program unit, after a module
// or function contains statement, or inside a module or function.
bool Pre(const parser::CompilerDirective &directive) {
assert(pftParentStack.size() > 0 &&
"At least the Program must be a parent");
if (pftParentStack.back().isA<lower::pft::Program>()) {
addUnit(
lower::pft::CompilerDirectiveUnit(directive, pftParentStack.back()));
assert(pftParentStack.size() > 0 && "no program");
lower::pft::PftNode &node = pftParentStack.back();
if (node.isA<lower::pft::Program>()) {
addUnit(lower::pft::CompilerDirectiveUnit(directive, node));
return false;
} else if ((node.isA<lower::pft::ModuleLikeUnit>() ||
node.isA<lower::pft::FunctionLikeUnit>())) {
assert(containsStmtStack.size() && "empty contains stack");
if (containsStmtStack.back()) {
addContainedUnit(lower::pft::CompilerDirectiveUnit{directive, node});
return false;
}
}
return enterConstructOrDirective(directive);
}
Expand All @@ -277,16 +297,18 @@ class PFTBuilder {
/// Initialize a new module-like unit and make it the builder's focus.
template <typename A>
bool enterModule(const A &mod) {
Fortran::lower::pft::ModuleLikeUnit &unit =
lower::pft::ModuleLikeUnit &unit =
addUnit(lower::pft::ModuleLikeUnit{mod, pftParentStack.back()});
functionList = &unit.nestedFunctions;
containsStmtStack.push_back(false);
containedUnitList = &unit.containedUnitList;
pushEvaluationList(&unit.evaluationList);
pftParentStack.emplace_back(unit);
LLVM_DEBUG(dumpScope(&unit.getScope()));
return true;
}

void exitModule() {
containsStmtStack.pop_back();
if (!evaluationListStack.empty())
popEvaluationList();
pftParentStack.pop_back();
Expand Down Expand Up @@ -344,12 +366,13 @@ class PFTBuilder {
const semantics::SemanticsContext &semanticsContext) {
cleanModuleEvaluationList();
endFunctionBody(); // enclosing host subprogram body, if any
Fortran::lower::pft::FunctionLikeUnit &unit =
addFunction(lower::pft::FunctionLikeUnit{func, pftParentStack.back(),
semanticsContext});
lower::pft::FunctionLikeUnit &unit =
addContainedUnit(lower::pft::FunctionLikeUnit{
func, pftParentStack.back(), semanticsContext});
labelEvaluationMap = &unit.labelEvaluationMap;
assignSymbolLabelMap = &unit.assignSymbolLabelMap;
functionList = &unit.nestedFunctions;
containsStmtStack.push_back(false);
containedUnitList = &unit.containedUnitList;
pushEvaluationList(&unit.evaluationList);
pftParentStack.emplace_back(unit);
LLVM_DEBUG(dumpScope(&unit.getScope()));
Expand All @@ -361,6 +384,7 @@ class PFTBuilder {
endFunctionBody();
analyzeBranches(nullptr, *evaluationListStack.back()); // add branch links
processEntryPoints();
containsStmtStack.pop_back();
popEvaluationList();
labelEvaluationMap = nullptr;
assignSymbolLabelMap = nullptr;
Expand All @@ -371,7 +395,7 @@ class PFTBuilder {
/// Initialize a new construct or directive and make it the builder's focus.
template <typename A>
bool enterConstructOrDirective(const A &constructOrDirective) {
Fortran::lower::pft::Evaluation &eval = addEvaluation(
lower::pft::Evaluation &eval = addEvaluation(
lower::pft::Evaluation{constructOrDirective, pftParentStack.back()});
eval.evaluationList.reset(new lower::pft::EvaluationList);
pushEvaluationList(eval.evaluationList.get());
Expand All @@ -381,7 +405,7 @@ class PFTBuilder {
}

void exitConstructOrDirective() {
auto isOpenMPLoopConstruct = [](Fortran::lower::pft::Evaluation *eval) {
auto isOpenMPLoopConstruct = [](lower::pft::Evaluation *eval) {
if (const auto *ompConstruct = eval->getIf<parser::OpenMPConstruct>())
if (std::holds_alternative<parser::OpenMPLoopConstruct>(
ompConstruct->u))
Expand All @@ -396,8 +420,7 @@ class PFTBuilder {
// construct region must have an exit target inside the region.
// This is not applicable to the OpenMP loop construct since the
// end of the loop is an available target inside the region.
Fortran::lower::pft::EvaluationList &evaluationList =
*eval->evaluationList;
lower::pft::EvaluationList &evaluationList = *eval->evaluationList;
if (!evaluationList.empty() && evaluationList.back().isConstruct()) {
static const parser::ContinueStmt exitTarget{};
addEvaluation(
Expand All @@ -413,15 +436,15 @@ class PFTBuilder {
void resetFunctionState() {
if (!pftParentStack.empty()) {
pftParentStack.back().visit(common::visitors{
[&](lower::pft::ModuleLikeUnit &p) {
containedUnitList = &p.containedUnitList;
},
[&](lower::pft::FunctionLikeUnit &p) {
functionList = &p.nestedFunctions;
containedUnitList = &p.containedUnitList;
labelEvaluationMap = &p.labelEvaluationMap;
assignSymbolLabelMap = &p.assignSymbolLabelMap;
},
[&](lower::pft::ModuleLikeUnit &p) {
functionList = &p.nestedFunctions;
},
[&](auto &) { functionList = nullptr; },
[&](auto &) { containedUnitList = nullptr; },
});
}
}
Expand All @@ -433,12 +456,11 @@ class PFTBuilder {
}

template <typename A>
A &addFunction(A &&func) {
if (functionList) {
functionList->emplace_back(std::move(func));
return functionList->back();
}
return addUnit(std::move(func));
A &addContainedUnit(A &&unit) {
if (!containedUnitList)
return addUnit(std::move(unit));
containedUnitList->emplace_back(std::move(unit));
return std::get<A>(containedUnitList->back());
}

// ActionStmt has a couple of non-conforming cases, explicitly handled here.
Expand All @@ -459,7 +481,6 @@ class PFTBuilder {

/// Append an Evaluation to the end of the current list.
lower::pft::Evaluation &addEvaluation(lower::pft::Evaluation &&eval) {
assert(functionList && "not in a function");
assert(!evaluationListStack.empty() && "empty evaluation list stack");
if (!constructAndDirectiveStack.empty())
eval.parentConstruct = constructAndDirectiveStack.back();
Expand Down Expand Up @@ -499,15 +520,15 @@ class PFTBuilder {

/// push a new list on the stack of Evaluation lists
void pushEvaluationList(lower::pft::EvaluationList *evaluationList) {
assert(functionList && "not in a function");
assert(evaluationList && evaluationList->empty() &&
"evaluation list isn't correct");
"invalid evaluation list");
evaluationListStack.emplace_back(evaluationList);
}

/// pop the current list and return to the last Evaluation list
void popEvaluationList() {
assert(functionList && "not in a function");
assert(!evaluationListStack.empty() &&
"trying to pop an empty evaluationListStack");
evaluationListStack.pop_back();
}

Expand Down Expand Up @@ -1089,16 +1110,16 @@ class PFTBuilder {
std::vector<lower::pft::PftNode> pftParentStack;
const semantics::SemanticsContext &semanticsContext;

/// functionList points to the internal or module procedure function list
/// of a FunctionLikeUnit or a ModuleLikeUnit. It may be null.
std::list<lower::pft::FunctionLikeUnit> *functionList{};
llvm::SmallVector<bool> containsStmtStack{};
lower::pft::ContainedUnitList *containedUnitList{};
std::vector<lower::pft::Evaluation *> constructAndDirectiveStack{};
std::vector<lower::pft::Evaluation *> doConstructStack{};
/// evaluationListStack is the current nested construct evaluationList state.
std::vector<lower::pft::EvaluationList *> evaluationListStack{};
llvm::DenseMap<parser::Label, lower::pft::Evaluation *> *labelEvaluationMap{};
lower::pft::SymbolLabelMap *assignSymbolLabelMap{};
std::map<std::string, lower::pft::Evaluation *> constructNameMap{};
int specificationPartLevel{};
lower::pft::Evaluation *lastLexicalEvaluation{};
};

Expand Down Expand Up @@ -1201,11 +1222,15 @@ class PFTDumper {
outputStream << " -> " << eval.controlSuccessor->printIndex;
else if (eval.isA<parser::EntryStmt>() && eval.lexicalSuccessor)
outputStream << " -> " << eval.lexicalSuccessor->printIndex;
bool extraNewline = false;
if (!eval.position.empty())
outputStream << ": " << eval.position.ToString();
else if (auto *dir = eval.getIf<Fortran::parser::CompilerDirective>())
else if (auto *dir = eval.getIf<parser::CompilerDirective>()) {
extraNewline = dir->source.ToString().back() == '\n';
outputStream << ": !" << dir->source.ToString();
outputStream << '\n';
}
if (!extraNewline)
outputStream << '\n';
if (eval.hasNestedEvaluations()) {
dumpEvaluationList(outputStream, *eval.evaluationList, indent + 1);
outputStream << indentString << "<<End " << name << bang << ">>\n";
Expand Down Expand Up @@ -1265,13 +1290,7 @@ class PFTDumper {
outputStream << ": " << header;
outputStream << '\n';
dumpEvaluationList(outputStream, functionLikeUnit.evaluationList);
if (!functionLikeUnit.nestedFunctions.empty()) {
outputStream << "\nContains\n";
for (const lower::pft::FunctionLikeUnit &func :
functionLikeUnit.nestedFunctions)
dumpFunctionLikeUnit(outputStream, func);
outputStream << "End Contains\n";
}
dumpContainedUnitList(outputStream, functionLikeUnit.containedUnitList);
outputStream << "End " << unitKind << ' ' << name << "\n\n";
}

Expand All @@ -1298,11 +1317,8 @@ class PFTDumper {
});
outputStream << unitKind << ' ' << name << ": " << header << '\n';
dumpEvaluationList(outputStream, moduleLikeUnit.evaluationList);
outputStream << "Contains\n";
for (const lower::pft::FunctionLikeUnit &func :
moduleLikeUnit.nestedFunctions)
dumpFunctionLikeUnit(outputStream, func);
outputStream << "End Contains\nEnd " << unitKind << ' ' << name << "\n\n";
dumpContainedUnitList(outputStream, moduleLikeUnit.containedUnitList);
outputStream << "End " << unitKind << ' ' << name << "\n\n";
}

// Top level directives
Expand All @@ -1311,18 +1327,43 @@ class PFTDumper {
const lower::pft::CompilerDirectiveUnit &directive) {
outputStream << getNodeIndex(directive) << " ";
outputStream << "CompilerDirective: !";
outputStream << directive.get<Fortran::parser::CompilerDirective>()
.source.ToString();
outputStream << "\nEnd CompilerDirective\n\n";
bool extraNewline =
directive.get<parser::CompilerDirective>().source.ToString().back() ==
'\n';
outputStream
<< directive.get<parser::CompilerDirective>().source.ToString();
if (!extraNewline)
outputStream << "\n";
outputStream << "\n";
}

void dumpContainedUnitList(
llvm::raw_ostream &outputStream,
const lower::pft::ContainedUnitList &containedUnitList) {
if (containedUnitList.empty())
return;
outputStream << "\nContains\n";
for (const lower::pft::ContainedUnit &unit : containedUnitList)
if (const auto *func = std::get_if<lower::pft::FunctionLikeUnit>(&unit)) {
dumpFunctionLikeUnit(outputStream, *func);
} else if (const auto *dir =
std::get_if<lower::pft::CompilerDirectiveUnit>(&unit)) {
outputStream << getNodeIndex(*dir) << " ";
dumpEvaluation(outputStream,
lower::pft::Evaluation{
dir->get<parser::CompilerDirective>(), dir->parent});
outputStream << "\n";
}
outputStream << "End Contains\n";
}

void
dumpOpenACCDirectiveUnit(llvm::raw_ostream &outputStream,
const lower::pft::OpenACCDirectiveUnit &directive) {
outputStream << getNodeIndex(directive) << " ";
outputStream << "OpenACCDirective: !$acc ";
outputStream << directive.get<Fortran::parser::OpenACCRoutineConstruct>()
.source.ToString();
outputStream
<< directive.get<parser::OpenACCRoutineConstruct>().source.ToString();
outputStream << "\nEnd OpenACCDirective\n\n";
}

Expand Down
Loading