11 changes: 4 additions & 7 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -6050,30 +6050,27 @@ class DeducedTemplateSpecializationType : public DeducedType,

DeducedTemplateSpecializationType(TemplateName Template,
QualType DeducedAsType,
bool IsDeducedAsDependent)
bool IsDeducedAsDependent, QualType Canon)
: DeducedType(DeducedTemplateSpecialization, DeducedAsType,
toTypeDependence(Template.getDependence()) |
(IsDeducedAsDependent
? TypeDependence::DependentInstantiation
: TypeDependence::None),
DeducedAsType.isNull() ? QualType(this, 0)
: DeducedAsType.getCanonicalType()),
Canon),
Template(Template) {}

public:
/// Retrieve the name of the template that we are deducing.
TemplateName getTemplateName() const { return Template;}

void Profile(llvm::FoldingSetNodeID &ID) {
void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, getTemplateName(), getDeducedType(), isDependentType());
}

static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Template,
QualType Deduced, bool IsDependent) {
Template.Profile(ID);
QualType CanonicalType =
Deduced.isNull() ? Deduced : Deduced.getCanonicalType();
ID.AddPointer(CanonicalType.getAsOpaquePtr());
Deduced.Profile(ID);
ID.AddBoolean(IsDependent || Template.isDependent());
}

Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -3633,7 +3633,7 @@ def NoThreadSafetyAnalysis : InheritableAttr {
def GuardedBy : InheritableAttr {
let Spellings = [GNU<"guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = LateAttrParseExperimentalExt;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3644,7 +3644,7 @@ def GuardedBy : InheritableAttr {
def PtGuardedBy : InheritableAttr {
let Spellings = [GNU<"pt_guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = LateAttrParseExperimentalExt;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3655,7 +3655,7 @@ def PtGuardedBy : InheritableAttr {
def AcquiredAfter : InheritableAttr {
let Spellings = [GNU<"acquired_after">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = LateAttrParseExperimentalExt;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3666,7 +3666,7 @@ def AcquiredAfter : InheritableAttr {
def AcquiredBefore : InheritableAttr {
let Spellings = [GNU<"acquired_before">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = LateAttrParseExperimentalExt;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping
///< regions.
CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria.
VALUE_CODEGENOPT(MCDCMaxConds, 16, 32767) ///< MC/DC Maximum conditions.
VALUE_CODEGENOPT(MCDCMaxTVs, 32, 0x7FFFFFFE) ///< MC/DC Maximum test vectors.

/// If -fpcc-struct-return or -freg-struct-return is specified.
ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -8779,6 +8779,9 @@ def err_typecheck_incomplete_type_not_modifiable_lvalue : Error<
def err_typecheck_lvalue_casts_not_supported : Error<
"assignment to cast is illegal, lvalue casts are not supported">;

def note_typecheck_add_deref_star_not_modifiable_lvalue : Note<
"add '*' to dereference it">;

def err_typecheck_duplicate_vector_components_not_mlvalue : Error<
"vector is not assignable (contains duplicate components)">;
def err_block_decl_ref_not_modifiable_lvalue : Error<
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,14 @@ defm mcdc_coverage : BoolFOption<"coverage-mcdc",
"Enable MC/DC criteria when generating code coverage">,
NegFlag<SetFalse, [], [ClangOption], "Disable MC/DC coverage criteria">,
BothFlags<[], [ClangOption, CLOption]>>;
def fmcdc_max_conditions_EQ : Joined<["-"], "fmcdc-max-conditions=">,
Group<f_Group>, Visibility<[CC1Option]>,
HelpText<"Maximum number of conditions in MC/DC coverage">,
MarshallingInfoInt<CodeGenOpts<"MCDCMaxConds">, "32767">;
def fmcdc_max_test_vectors_EQ : Joined<["-"], "fmcdc-max-test-vectors=">,
Group<f_Group>, Visibility<[CC1Option]>,
HelpText<"Maximum number of test vectors in MC/DC coverage">,
MarshallingInfoInt<CodeGenOpts<"MCDCMaxTVs">, "0x7FFFFFFE">;
def fprofile_generate : Flag<["-"], "fprofile-generate">,
Group<f_Group>, Visibility<[ClangOption, CLOption]>,
HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ class FrontendOptions {
std::string ProductName;

// Currently this is only used as part of the `-extract-api` action.
// A comma seperated list of files providing a list of APIs to
// A comma separated list of files providing a list of APIs to
// ignore when extracting documentation.
std::vector<std::string> ExtractAPIIgnoresFileList;

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/InstallAPI/DylibVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class DylibVerifier : llvm::MachO::RecordVisitor {

// Check if an internal declaration in zippered library has an
// external declaration for a different platform. This results
// in the symbol being in a "seperate" platform slice.
// in the symbol being in a "separate" platform slice.
bool shouldIgnoreInternalZipperedSymbol(const Record *R,
const SymbolContext &SymCtx) const;

Expand Down
14 changes: 0 additions & 14 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3128,20 +3128,6 @@ class Parser : public CodeCompletionHandler {
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
ParsedAttr::Form Form);

void ParseGuardedByAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc, SourceLocation *EndLoc,
ParsedAttr::Form Form);

void ParseAcquiredAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc, SourceLocation *EndLoc,
ParsedAttr::Form Form);

void ParseTypeofSpecifier(DeclSpec &DS);
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
Expand Down
7 changes: 4 additions & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -5142,7 +5142,7 @@ class Sema final : public SemaBase {
enum ExpressionKind {
EK_Decltype,
EK_TemplateArgument,
EK_AttrArgument,
EK_BoundsAttrArgument,
EK_Other
} ExprContext;

Expand Down Expand Up @@ -5249,9 +5249,10 @@ class Sema final : public SemaBase {
return const_cast<Sema *>(this)->parentEvaluationContext();
};

bool isAttrContext() const {
bool isBoundsAttrContext() const {
return ExprEvalContexts.back().ExprContext ==
ExpressionEvaluationContextRecord::ExpressionKind::EK_AttrArgument;
ExpressionEvaluationContextRecord::ExpressionKind::
EK_BoundsAttrArgument;
}

/// Increment when we find a reference; decrement when we find an ignored
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@ class MemRegionManager {
/// associated element type, index, and super region.
const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
const SubRegion *superRegion,
ASTContext &Ctx);
const ASTContext &Ctx);

const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
const SubRegion *superRegion) {
Expand Down
84 changes: 46 additions & 38 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@
#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 @@ -5926,11 +5925,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 @@ -5941,7 +5938,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 @@ -5950,6 +5948,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 @@ -13664,20 +13676,17 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const {
}
}

// 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;
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;
}

ParsedTargetAttr
Expand Down Expand Up @@ -13712,12 +13721,10 @@ 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.
// 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());
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 @@ -13738,31 +13745,32 @@ 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());
std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats);
for (StringRef Feat : Feats)
if (Target->validateCpuSupports(Feat.str()))
// Use '?' to mark features that came from AArch64 TargetClones.
Features.push_back("?" + Feat.str());
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);
}
} else if (const auto *TV = FD->getAttr<TargetVersionAttr>()) {
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 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);
} else {
FeatureMap = Target->getTargetOpts().FeatureMap;
}
Expand Down
2 changes: 0 additions & 2 deletions clang/lib/AST/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,4 @@ add_clang_library(clangAST
omp_gen
ClangDriverOptions
intrinsics_gen
# These generated headers are included transitively.
AArch64TargetParserTableGen
)
4 changes: 2 additions & 2 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14014,8 +14014,8 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
QualType Ty = E->getTypeOfArgument();
// If the vector has a fixed size, we can determine the number of elements
// at compile time.
if (Ty->isVectorType())
return Success(Ty->castAs<VectorType>()->getNumElements(), E);
if (const auto *VT = Ty->getAs<VectorType>())
return Success(VT->getNumElements(), E);

assert(Ty->isSizelessVectorType());
if (Info.InConstantContext)
Expand Down
35 changes: 33 additions & 2 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
}

case CK_IntegralToBoolean:
case CK_BooleanToSignedIntegral:
case CK_IntegralCast: {
if (DiscardResult)
return this->discard(SubExpr);
Expand All @@ -362,7 +363,12 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {

if (FromT == ToT)
return true;
return this->emitCast(*FromT, *ToT, CE);
if (!this->emitCast(*FromT, *ToT, CE))
return false;

if (CE->getCastKind() == CK_BooleanToSignedIntegral)
return this->emitNeg(*ToT, CE);
return true;
}

case CK_PointerToBoolean:
Expand Down Expand Up @@ -1201,6 +1207,23 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
}

if (T->isArrayType()) {
// Prepare composite return value.
if (!Initializing) {
if (GlobalDecl) {
std::optional<unsigned> GlobalIndex = P.createGlobal(E);
if (!GlobalIndex)
return false;
if (!this->emitGetPtrGlobal(*GlobalIndex, E))
return false;
} else {
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
}
}

unsigned ElementIndex = 0;
for (const Expr *Init : Inits) {
if (!this->visitArrayElemInit(ElementIndex, Init))
Expand Down Expand Up @@ -3948,9 +3971,17 @@ bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
// we haven't seen yet.
if (Ctx.getLangOpts().CPlusPlus) {
if (const auto *VD = dyn_cast<VarDecl>(D)) {
const auto typeShouldBeVisited = [&](QualType T) -> bool {
if (T.isConstant(Ctx.getASTContext()))
return true;
if (const auto *RT = T->getAs<ReferenceType>())
return RT->getPointeeType().isConstQualified();
return false;
};

// Visit local const variables like normal.
if ((VD->isLocalVarDecl() || VD->isStaticDataMember()) &&
VD->getType().isConstant(Ctx.getASTContext())) {
typeShouldBeVisited(VD->getType())) {
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
2 changes: 1 addition & 1 deletion clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,7 @@ void TextNodeDumper::dumpTemplateName(TemplateName TN, StringRef Label) {
llvm::raw_svector_ostream SS(Str);
TN.print(SS, PrintPolicy);
}
OS << " '" << Str << "'";
OS << "'" << Str << "'";

if (Context) {
if (TemplateName CanonTN = Context->getCanonicalTemplateName(TN);
Expand Down
105 changes: 72 additions & 33 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1052,18 +1052,57 @@ 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 @@ -1073,26 +1112,23 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
bool FoundArch = false;

auto SplitAndAddFeatures = [](StringRef FeatString,
std::vector<std::string> &Features,
llvm::AArch64::ExtensionSet &FeatureBits) {
std::vector<std::string> &Features) {
SmallVector<StringRef, 8> SplitFeatures;
FeatString.split(SplitFeatures, StringRef("+"), -1, false);
for (StringRef Feature : SplitFeatures) {
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());
StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
if (!FeatureName.empty())
Features.push_back(FeatureName.str());
else
Features.push_back("+" + Feature.str());
// 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());
}
};

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 @@ -1115,9 +1151,9 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
// Ret.Features.
if (!AI)
continue;
FeatureBits.addArchDefaults(*AI);
Ret.Features.push_back(AI->ArchFeature.str());
// Add any extra features, after the +
SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
SplitAndAddFeatures(Split.second, Ret.Features);
} else if (Feature.starts_with("cpu=")) {
if (!Ret.CPU.empty())
Ret.Duplicate = "cpu=";
Expand All @@ -1127,30 +1163,33 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
std::pair<StringRef, StringRef> Split =
Feature.split("=").second.trim().split("+");
Ret.CPU = Split.first;
if (auto CpuInfo = llvm::AArch64::parseCpu(Ret.CPU)) {
FeatureBits.addCPUDefaults(*CpuInfo);
SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
}
SplitAndAddFeatures(Split.second, Ret.Features);
}
} 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, FeatureBits);
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());
} else {
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());
// 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());
else
Ret.Features.push_back("+" + Feature.str());
}
}
FeatureBits.toLLVMFeatureList(Ret.Features);
return Ret;
}

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ 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
50 changes: 27 additions & 23 deletions clang/lib/CodeGen/CodeGenPGO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,6 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
PGOHash Hash;
/// The map of statements to counters.
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
/// The next bitmap byte index to assign.
unsigned NextMCDCBitmapIdx;
/// The state of MC/DC Coverage in this function.
MCDC::State &MCDCState;
/// Maximum number of supported MC/DC conditions in a boolean expression.
Expand All @@ -183,7 +181,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
MCDC::State &MCDCState, unsigned MCDCMaxCond,
DiagnosticsEngine &Diag)
: NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
NextMCDCBitmapIdx(0), MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
ProfileVersion(ProfileVersion), Diag(Diag) {}

// Blocks and lambdas are handled as separate functions, so we need not
Expand Down Expand Up @@ -314,11 +312,8 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
return true;
}

// Otherwise, allocate the number of bytes required for the bitmap
// based on the number of conditions. Must be at least 1-byte long.
MCDCState.DecisionByStmt[BinOp].BitmapIdx = NextMCDCBitmapIdx;
unsigned SizeInBits = std::max<unsigned>(1L << NumCond, CHAR_BIT);
NextMCDCBitmapIdx += SizeInBits / CHAR_BIT;
// Otherwise, allocate the Decision.
MCDCState.DecisionByStmt[BinOp].BitmapIdx = 0;
}
return true;
}
Expand Down Expand Up @@ -1083,7 +1078,9 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
// for most embedded applications. Setting a maximum value prevents the
// bitmap footprint from growing too large without the user's knowledge. In
// the future, this value could be adjusted with a command-line option.
unsigned MCDCMaxConditions = (CGM.getCodeGenOpts().MCDCCoverage) ? 6 : 0;
unsigned MCDCMaxConditions =
(CGM.getCodeGenOpts().MCDCCoverage ? CGM.getCodeGenOpts().MCDCMaxConds
: 0);

RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
RegionMCDCState.reset(new MCDC::State);
Expand All @@ -1099,7 +1096,6 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
NumRegionCounters = Walker.NextCounter;
RegionMCDCState->BitmapBytes = Walker.NextMCDCBitmapIdx;
FunctionHash = Walker.Hash.finalize();
}

Expand Down Expand Up @@ -1232,7 +1228,7 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) {
// anything.
llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(RegionMCDCState->BitmapBytes)};
Builder.getInt32(RegionMCDCState->BitmapBits)};
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
}
Expand All @@ -1250,6 +1246,11 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
return;

// Don't create tvbitmap_update if the record is allocated but excluded.
// Or `bitmap |= (1 << 0)` would be wrongly executed to the next bitmap.
if (DecisionStateIter->second.Indices.size() == 0)
return;

// Extract the offset of the global bitmap associated with this expression.
unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
Expand All @@ -1261,7 +1262,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
// index represents an executed test vector.
llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(RegionMCDCState->BitmapBytes),
Builder.getInt32(0), // Unused
Builder.getInt32(MCDCTestVectorBitmapOffset),
MCDCCondBitmapAddr.emitRawPointer(CGF)};
Builder.CreateCall(
Expand Down Expand Up @@ -1305,19 +1306,22 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
// Extract the ID of the condition we are setting in the bitmap.
const auto &Branch = BranchStateIter->second;
assert(Branch.ID >= 0 && "Condition has no ID!");
assert(Branch.DecisionStmt);

auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
// Cancel the emission if the Decision is erased after the allocation.
const auto DecisionIter =
RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
if (DecisionIter == RegionMCDCState->DecisionByStmt.end())
return;

// Emit intrinsic that updates a dedicated temporary value on the stack after
// a condition is evaluated. After the set of conditions has been updated,
// the resulting value is used to update the boolean expression's bitmap.
llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(Branch.ID),
MCDCCondBitmapAddr.emitRawPointer(CGF), Val};
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update),
Args);
const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];

auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
"mcdc." + Twine(Branch.ID + 1) + ".cur");
auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[true]));
NewTV = Builder.CreateSelect(
Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[false])));
Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
}

void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {
Expand Down
77 changes: 72 additions & 5 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ class SourceMappingRegion {
return std::holds_alternative<mcdc::BranchParameters>(MCDCParams);
}

const auto &getMCDCBranchParams() const {
return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams);
}

bool isMCDCDecision() const {
return std::holds_alternative<mcdc::DecisionParameters>(MCDCParams);
}
Expand All @@ -204,6 +208,8 @@ class SourceMappingRegion {
}

const mcdc::Parameters &getMCDCParams() const { return MCDCParams; }

void resetMCDCParams() { MCDCParams = mcdc::Parameters(); }
};

/// Spelling locations for the start and end of a source region.
Expand Down Expand Up @@ -748,6 +754,7 @@ struct MCDCCoverageBuilder {

llvm::SmallVector<mcdc::ConditionIDs> DecisionStack;
MCDC::State &MCDCState;
const Stmt *DecisionStmt = nullptr;
mcdc::ConditionID NextID = 0;
bool NotMapped = false;

Expand Down Expand Up @@ -777,7 +784,8 @@ struct MCDCCoverageBuilder {

/// Set the given condition's ID.
void setCondID(const Expr *Cond, mcdc::ConditionID ID) {
MCDCState.BranchByStmt[CodeGenFunction::stripCond(Cond)].ID = ID;
MCDCState.BranchByStmt[CodeGenFunction::stripCond(Cond)] = {ID,
DecisionStmt};
}

/// Return the ID of a given condition.
Expand Down Expand Up @@ -808,6 +816,11 @@ struct MCDCCoverageBuilder {
if (NotMapped)
return;

if (NextID == 0) {
DecisionStmt = E;
assert(MCDCState.DecisionByStmt.contains(E));
}

const mcdc::ConditionIDs &ParentDecision = DecisionStack.back();

// If the operator itself has an assigned ID, this means it represents a
Expand Down Expand Up @@ -2122,20 +2135,70 @@ struct CounterCoverageMappingBuilder
subtractCounters(ParentCount, TrueCount));
}

void createDecision(const BinaryOperator *E) {
void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
unsigned NumConds = MCDCBuilder.getTotalConditionsAndReset(E);
if (NumConds == 0)
return;

// Extract [ID, Conds] to construct the graph.
llvm::SmallVector<mcdc::ConditionIDs> CondIDs(NumConds);
for (const auto &SR : ArrayRef(SourceRegions).slice(Since)) {
if (SR.isMCDCBranch()) {
auto [ID, Conds] = SR.getMCDCBranchParams();
CondIDs[ID] = Conds;
}
}

// Construct the graph and calculate `Indices`.
mcdc::TVIdxBuilder Builder(CondIDs);
unsigned NumTVs = Builder.NumTestVectors;
unsigned MaxTVs = CVM.getCodeGenModule().getCodeGenOpts().MCDCMaxTVs;
assert(MaxTVs < mcdc::TVIdxBuilder::HardMaxTVs);

if (NumTVs > MaxTVs) {
// NumTVs exceeds MaxTVs -- warn and cancel the Decision.
cancelDecision(E, Since, NumTVs, MaxTVs);
return;
}

// Update the state for CodeGenPGO
assert(MCDCState.DecisionByStmt.contains(E));
MCDCState.DecisionByStmt[E] = {
MCDCState.BitmapBits, // Top
std::move(Builder.Indices),
};

auto DecisionParams = mcdc::DecisionParameters{
MCDCState.DecisionByStmt[E].BitmapIdx,
MCDCState.BitmapBits += NumTVs, // Tail
NumConds,
};

// Create MCDC Decision Region.
createDecisionRegion(E, DecisionParams);
}

// Warn and cancel the Decision.
void cancelDecision(const BinaryOperator *E, unsigned Since, int NumTVs,
int MaxTVs) {
auto &Diag = CVM.getCodeGenModule().getDiags();
unsigned DiagID =
Diag.getCustomDiagID(DiagnosticsEngine::Warning,
"unsupported MC/DC boolean expression; "
"number of test vectors (%0) exceeds max (%1). "
"Expression will not be covered");
Diag.Report(E->getBeginLoc(), DiagID) << NumTVs << MaxTVs;

// Restore MCDCBranch to Branch.
for (auto &SR : MutableArrayRef(SourceRegions).slice(Since)) {
assert(!SR.isMCDCDecision() && "Decision shouldn't be seen here");
if (SR.isMCDCBranch())
SR.resetMCDCParams();
}

// Tell CodeGenPGO not to instrument.
MCDCState.DecisionByStmt.erase(E);
}

/// Check if E belongs to system headers.
bool isExprInSystemHeader(const BinaryOperator *E) const {
return (!SystemHeadersCoverage &&
Expand All @@ -2152,6 +2215,8 @@ struct CounterCoverageMappingBuilder

bool IsRootNode = MCDCBuilder.isIdle();

unsigned SourceRegionsSince = SourceRegions.size();

// Keep track of Binary Operator and assign MCDC condition IDs.
MCDCBuilder.pushAndAssignIDs(E);

Expand Down Expand Up @@ -2190,7 +2255,7 @@ struct CounterCoverageMappingBuilder

// Create MCDC Decision Region if at top-level (root).
if (IsRootNode)
createDecision(E);
createOrCancelDecision(E, SourceRegionsSince);
}

// Determine whether the right side of OR operation need to be visited.
Expand All @@ -2211,6 +2276,8 @@ struct CounterCoverageMappingBuilder

bool IsRootNode = MCDCBuilder.isIdle();

unsigned SourceRegionsSince = SourceRegions.size();

// Keep track of Binary Operator and assign MCDC condition IDs.
MCDCBuilder.pushAndAssignIDs(E);

Expand Down Expand Up @@ -2253,7 +2320,7 @@ struct CounterCoverageMappingBuilder

// Create MCDC Decision Region if at top-level (root).
if (IsRootNode)
createDecision(E);
createOrCancelDecision(E, SourceRegionsSince);
}

void VisitLambdaExpr(const LambdaExpr *LE) {
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/CodeGen/MCDCState.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define LLVM_CLANG_LIB_CODEGEN_MCDCSTATE_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ProfileData/Coverage/MCDCTypes.h"

namespace clang {
Expand All @@ -26,16 +27,18 @@ using namespace llvm::coverage::mcdc;

/// Per-Function MC/DC state
struct State {
unsigned BitmapBytes = 0;
unsigned BitmapBits = 0;

struct Decision {
unsigned BitmapIdx;
llvm::SmallVector<std::array<int, 2>> Indices;
};

llvm::DenseMap<const Stmt *, Decision> DecisionByStmt;

struct Branch {
ConditionID ID;
const Stmt *DecisionStmt;
};

llvm::DenseMap<const Stmt *, Branch> BranchByStmt;
Expand Down
13 changes: 11 additions & 2 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1257,14 +1257,23 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const {
if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||
(isTargetIOSBased() && isIPhoneOSVersionLT(9)))
return 2;
return 4;
// Default to use DWARF 4 on OS X 10.11 - macOS 14 / iOS 9 - iOS 17.
if ((isTargetMacOSBased() && isMacosxVersionLT(15)) ||
(isTargetIOSBased() && isIPhoneOSVersionLT(18)) ||
(isTargetWatchOSBased() && TargetVersion < llvm::VersionTuple(11)) ||
(isTargetXROS() && TargetVersion < llvm::VersionTuple(2)) ||
(isTargetDriverKit() && TargetVersion < llvm::VersionTuple(24)) ||
(isTargetMacOSBased() &&
TargetVersion.empty())) // apple-darwin, no version.
return 4;
return 5;
}

void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
StringRef Component, RuntimeLinkOptions Opts,
bool IsShared) const {
SmallString<64> DarwinLibName = StringRef("libclang_rt.");
// an Darwin the builtins compomnent is not in the library name
// On Darwin the builtins component is not in the library name.
if (Component != "builtins") {
DarwinLibName += Component;
if (!(Opts & RLO_IsEmbedded))
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/InstallAPI/Visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
if (isa<ParmVarDecl>(D))
return true;

// Skip variables in records. They are handled seperately for C++.
// Skip variables in records. They are handled separately for C++.
if (D->getDeclContext()->isRecord())
return true;

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Lex/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2262,7 +2262,6 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,
unsigned PrefixLen = 0;

while (PrefixLen != 16 && isRawStringDelimBody(CurPtr[PrefixLen])) {
++PrefixLen;
if (!isLexingRawMode() &&
llvm::is_contained({'$', '@', '`'}, CurPtr[PrefixLen])) {
const char *Pos = &CurPtr[PrefixLen];
Expand All @@ -2271,6 +2270,7 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,
: diag::ext_cxx26_raw_string_literal_character_set)
<< StringRef(Pos, 1);
}
++PrefixLen;
}

// If the last character was not a '(', then we didn't lex a valid delimiter.
Expand Down
118 changes: 1 addition & 117 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,16 +671,6 @@ void Parser::ParseGNUAttributeArgs(
ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
Form);
return;
} else if (AttrKind == ParsedAttr::AT_GuardedBy ||
AttrKind == ParsedAttr::AT_PtGuardedBy) {
ParseGuardedByAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
EndLoc, Form);
return;
} else if (AttrKind == ParsedAttr::AT_AcquiredAfter ||
AttrKind == ParsedAttr::AT_AcquiredBefore) {
ParseAcquiredAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
EndLoc, Form);
return;
} else if (AttrKind == ParsedAttr::AT_CXXAssume) {
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
return;
Expand Down Expand Up @@ -3340,112 +3330,6 @@ void Parser::DistributeCLateParsedAttrs(Decl *Dcl,
}
}

/// GuardedBy attributes (e.g., guarded_by):
/// AttrName '(' expression ')'
void Parser::ParseGuardedByAttribute(
IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
SourceLocation *EndLoc, ParsedAttr::Form Form) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");

BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();

if (Tok.is(tok::r_paren)) {
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
Parens.consumeClose();
return;
}

ArgsVector ArgExprs;
// Don't evaluate argument when the attribute is ignored.
using ExpressionKind =
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
EnterExpressionEvaluationContext EC(
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,
ExpressionKind::EK_AttrArgument);

ExprResult ArgExpr(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));

if (ArgExpr.isInvalid()) {
Parens.skipToEnd();
return;
}

ArgExprs.push_back(ArgExpr.get());

auto RParens = Tok.getLocation();
auto &AL =
*Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, RParens), ScopeName,
ScopeLoc, ArgExprs.data(), ArgExprs.size(), Form);

if (EndLoc)
*EndLoc = RParens;

if (!Tok.is(tok::r_paren)) {
Diag(Tok.getLocation(), diag::err_attribute_wrong_number_arguments)
<< AL << 1;
Parens.skipToEnd();
return;
}

Parens.consumeClose();
}

/// Acquired attributes (e.g., acquired_before, acquired_after):
/// AttrName '(' expression-list ')'
void Parser::ParseAcquiredAttribute(
IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
SourceLocation *EndLoc, ParsedAttr::Form Form) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");

BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();

if (Tok.is(tok::r_paren)) {
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
Parens.consumeClose();
return;
}

auto ArgStart = Tok.getLocation();

ArgsVector ArgExprs;

do {

// Don't evaluate argument when the attribute is ignored.
using ExpressionKind =
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
EnterExpressionEvaluationContext EC(
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
nullptr, ExpressionKind::EK_AttrArgument);

ExprResult ArgExpr(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));

if (ArgExpr.isInvalid()) {
Parens.skipToEnd();
return;
}

ArgExprs.push_back(ArgExpr.get());

} while (TryConsumeToken(tok::comma));

auto ArgEnd = Tok.getLocation();

Attrs.addNew(&AttrName, SourceRange(ArgStart, ArgEnd), ScopeName, ScopeLoc,
ArgExprs.data(), ArgExprs.size(), Form);

if (EndLoc)
*EndLoc = ArgEnd;

Parens.consumeClose();
}

/// Bounds attributes (e.g., counted_by):
/// AttrName '(' expression ')'
void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
Expand All @@ -3471,7 +3355,7 @@ void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
EnterExpressionEvaluationContext EC(
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,
ExpressionKind::EK_AttrArgument);
ExpressionKind::EK_BoundsAttrArgument);

ExprResult ArgExpr(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
Expand Down
28 changes: 24 additions & 4 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2723,7 +2723,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// appertains to a type of C struct field such that the name lookup
// within a struct finds the member name, which is not the case for other
// contexts in C.
if (isAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
if (isBoundsAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
// See if this is reference to a field of struct.
LookupResult R(*this, NameInfo, LookupMemberName);
// LookupName handles a name lookup from within anonymous struct.
Expand Down Expand Up @@ -3357,7 +3357,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
case Decl::Field:
case Decl::IndirectField:
case Decl::ObjCIvar:
assert((getLangOpts().CPlusPlus || isAttrContext()) &&
assert((getLangOpts().CPlusPlus || isBoundsAttrContext()) &&
"building reference to field in C?");

// These can't have reference type in well-formed programs, but
Expand Down Expand Up @@ -13288,6 +13288,23 @@ enum {
ConstUnknown, // Keep as last element
};

static void MaybeSuggestDerefFixIt(Sema &S, const Expr *E, SourceLocation Loc) {
ExprResult Deref;
Expr *TE = const_cast<Expr *>(E);
{
Sema::TentativeAnalysisScope Trap(S);
Deref = S.ActOnUnaryOp(S.getCurScope(), Loc, tok::star, TE);
}
if (Deref.isUsable() &&
Deref.get()->isModifiableLvalue(S.Context, &Loc) == Expr::MLV_Valid &&
!E->getType()->isObjCObjectPointerType()) {
S.Diag(E->getBeginLoc(),
diag::note_typecheck_add_deref_star_not_modifiable_lvalue)
<< E->getSourceRange()
<< FixItHint::CreateInsertion(E->getBeginLoc(), "*");
}
}

/// Emit the "read-only variable not assignable" error and print notes to give
/// more information about why the variable is not assignable, such as pointing
/// to the declaration of a const variable, showing that a method is const, or
Expand Down Expand Up @@ -13382,6 +13399,7 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const)
<< ExprRange << ConstVariable << VD << VD->getType();
MaybeSuggestDerefFixIt(S, E, Loc);
DiagnosticEmitted = true;
}
S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
Expand Down Expand Up @@ -13602,10 +13620,12 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
SourceRange Assign;
if (Loc != OrigLoc)
Assign = SourceRange(OrigLoc, OrigLoc);
if (NeedType)
if (NeedType) {
S.Diag(Loc, DiagID) << E->getType() << E->getSourceRange() << Assign;
else
} else {
S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
MaybeSuggestDerefFixIt(S, E, Loc);
}
return true;
}

Expand Down
22 changes: 18 additions & 4 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ class InitListChecker {
: InitListChecker(S, Entity, IL, T, /*VerifyOnly=*/true,
/*TreatUnavailableAsInvalid=*/false,
/*InOverloadResolution=*/false,
&AggrDeductionCandidateParamTypes){};
&AggrDeductionCandidateParamTypes) {}

bool HadError() { return hadError; }

Expand Down Expand Up @@ -1443,7 +1443,21 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// dependent non-array type or an array type with a value-dependent
// bound
assert(AggrDeductionCandidateParamTypes);
if (!isa_and_nonnull<ConstantArrayType>(

// In the presence of a braced-init-list within the initializer, we should
// not perform brace-elision, even if brace elision would otherwise be
// applicable. For example, given:
//
// template <class T> struct Foo {
// T t[2];
// };
//
// Foo t = {{1, 2}};
//
// we don't want the (T, T) but rather (T [2]) in terms of the initializer
// {{1, 2}}.
if (isa<InitListExpr, DesignatedInitExpr>(expr) ||
!isa_and_present<ConstantArrayType>(
SemaRef.Context.getAsArrayType(ElemType))) {
++Index;
AggrDeductionCandidateParamTypes->push_back(ElemType);
Expand Down Expand Up @@ -10940,14 +10954,14 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
// if e_i is of array type and x_i is a braced-init-list, T_i is an
// rvalue reference to the declared type of e_i and
// C++ [over.match.class.deduct]p1.9:
// if e_i is of array type and x_i is a bstring-literal, T_i is an
// if e_i is of array type and x_i is a string-literal, T_i is an
// lvalue reference to the const-qualified declared type of e_i and
// C++ [over.match.class.deduct]p1.10:
// otherwise, T_i is the declared type of e_i
for (int I = 0, E = ListInit->getNumInits();
I < E && !isa<PackExpansionType>(ElementTypes[I]); ++I)
if (ElementTypes[I]->isArrayType()) {
if (isa<InitListExpr>(ListInit->getInit(I)))
if (isa<InitListExpr, DesignatedInitExpr>(ListInit->getInit(I)))
ElementTypes[I] = Context.getRValueReferenceType(ElementTypes[I]);
else if (isa<StringLiteral>(
ListInit->getInit(I)->IgnoreParenImpCasts()))
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1980,21 +1980,21 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType,
return false;

// There are no conversions between extended vector types, only identity.
if (ToType->isExtVectorType()) {
if (FromType->isExtVectorType()) {
if (auto *ToExtType = ToType->getAs<ExtVectorType>()) {
if (auto *FromExtType = FromType->getAs<ExtVectorType>()) {
// HLSL allows implicit truncation of vector types.
if (S.getLangOpts().HLSL) {
unsigned FromElts = FromType->getAs<VectorType>()->getNumElements();
unsigned ToElts = ToType->getAs<VectorType>()->getNumElements();
unsigned FromElts = FromExtType->getNumElements();
unsigned ToElts = ToExtType->getNumElements();
if (FromElts < ToElts)
return false;
if (FromElts == ToElts)
ICK = ICK_Identity;
else
ICK = ICK_HLSL_Vector_Truncation;

QualType FromElTy = FromType->getAs<VectorType>()->getElementType();
QualType ToElTy = ToType->getAs<VectorType>()->getElementType();
QualType FromElTy = FromExtType->getElementType();
QualType ToElTy = ToExtType->getElementType();
if (S.Context.hasSameUnqualifiedType(FromElTy, ToElTy))
return true;
return IsVectorElementConversion(S, FromElTy, ToElTy, ElConv, From);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace clang {
unsigned AbbrevToUse;

/// A helper that can help us to write a packed bit across function
/// calls. For example, we may write seperate bits in seperate functions:
/// calls. For example, we may write separate bits in separate functions:
///
/// void VisitA(A* a) {
/// Record.push_back(a->isSomething());
Expand Down
136 changes: 125 additions & 11 deletions clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,18 +717,56 @@ const ExplodedNode *StreamChecker::getAcquisitionSite(const ExplodedNode *N,
return nullptr;
}

static std::optional<int64_t> getKnownValue(ProgramStateRef State, SVal V) {
SValBuilder &SVB = State->getStateManager().getSValBuilder();
if (const llvm::APSInt *Int = SVB.getKnownValue(State, V))
return Int->tryExtValue();
return std::nullopt;
}

/// Invalidate only the requested elements instead of the whole buffer.
/// This is basically a refinement of the more generic 'escapeArgs' or
/// the plain old 'invalidateRegions'.
static ProgramStateRef
escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
unsigned BlockCount, const SubRegion *Buffer,
QualType ElemType, int64_t StartIndex,
int64_t ElementCount) {
constexpr auto DoNotInvalidateSuperRegion =
RegionAndSymbolInvalidationTraits::InvalidationKinds::
TK_DoNotInvalidateSuperRegion;

const LocationContext *LCtx = Call.getLocationContext();
const ASTContext &Ctx = State->getStateManager().getContext();
SValBuilder &SVB = State->getStateManager().getSValBuilder();
auto &RegionManager = Buffer->getMemRegionManager();

SmallVector<SVal> EscapingVals;
EscapingVals.reserve(ElementCount);

RegionAndSymbolInvalidationTraits ITraits;
for (auto Idx : llvm::seq(StartIndex, StartIndex + ElementCount)) {
NonLoc Index = SVB.makeArrayIndex(Idx);
const auto *Element =
RegionManager.getElementRegion(ElemType, Index, Buffer, Ctx);
EscapingVals.push_back(loc::MemRegionVal(Element));
ITraits.setTrait(Element, DoNotInvalidateSuperRegion);
}
return State->invalidateRegions(
EscapingVals, Call.getOriginExpr(), BlockCount, LCtx,
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr, &Call, &ITraits);
}

static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C,
const CallEvent &Call,
ArrayRef<unsigned int> EscapingArgs) {
const auto *CE = Call.getOriginExpr();

SmallVector<SVal> EscapingVals;
EscapingVals.reserve(EscapingArgs.size());
for (auto EscArgIdx : EscapingArgs)
EscapingVals.push_back(Call.getArgSVal(EscArgIdx));
State = State->invalidateRegions(EscapingVals, CE, C.blockCount(),
C.getLocationContext(),
/*CausesPointerEscape=*/false);
auto GetArgSVal = [&Call](int Idx) { return Call.getArgSVal(Idx); };
auto EscapingVals = to_vector(map_range(EscapingArgs, GetArgSVal));
State = State->invalidateRegions(EscapingVals, Call.getOriginExpr(),
C.blockCount(), C.getLocationContext(),
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr);
return State;
}

Expand Down Expand Up @@ -907,6 +945,76 @@ void StreamChecker::preWrite(const FnDescription *Desc, const CallEvent &Call,
C.addTransition(State);
}

static std::optional<QualType> getPointeeType(const MemRegion *R) {
if (!R)
return std::nullopt;
if (const auto *ER = dyn_cast<ElementRegion>(R))
return ER->getElementType();
if (const auto *TR = dyn_cast<TypedValueRegion>(R))
return TR->getValueType();
if (const auto *SR = dyn_cast<SymbolicRegion>(R))
return SR->getPointeeStaticType();
return std::nullopt;
}

static std::optional<NonLoc> getStartIndex(SValBuilder &SVB,
const MemRegion *R) {
if (!R)
return std::nullopt;

auto Zero = [&SVB] {
BasicValueFactory &BVF = SVB.getBasicValueFactory();
return nonloc::ConcreteInt(BVF.getIntValue(0, /*isUnsigned=*/false));
};

if (const auto *ER = dyn_cast<ElementRegion>(R))
return ER->getIndex();
if (const auto *TR = dyn_cast<TypedValueRegion>(R))
return Zero();
if (const auto *SR = dyn_cast<SymbolicRegion>(R))
return Zero();
return std::nullopt;
}

static ProgramStateRef
tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C,
const CallEvent &Call, NonLoc SizeVal,
NonLoc NMembVal) {
// Try to invalidate the individual elements.
const auto *Buffer =
dyn_cast_or_null<SubRegion>(Call.getArgSVal(0).getAsRegion());

std::optional<QualType> ElemTy = getPointeeType(Buffer);
std::optional<SVal> StartElementIndex =
getStartIndex(C.getSValBuilder(), Buffer);

// Drop the outermost ElementRegion to get the buffer.
if (const auto *ER = dyn_cast_or_null<ElementRegion>(Buffer))
Buffer = dyn_cast<SubRegion>(ER->getSuperRegion());

std::optional<int64_t> CountVal = getKnownValue(State, NMembVal);
std::optional<int64_t> Size = getKnownValue(State, SizeVal);
std::optional<int64_t> StartIndexVal =
getKnownValue(State, StartElementIndex.value_or(UnknownVal()));

if (ElemTy && CountVal && Size && StartIndexVal) {
int64_t NumBytesRead = Size.value() * CountVal.value();
int64_t ElemSizeInChars =
C.getASTContext().getTypeSizeInChars(*ElemTy).getQuantity();
bool IncompleteLastElement = (NumBytesRead % ElemSizeInChars) != 0;
int64_t NumCompleteOrIncompleteElementsRead =
NumBytesRead / ElemSizeInChars + IncompleteLastElement;

constexpr int MaxInvalidatedElementsLimit = 64;
if (NumCompleteOrIncompleteElementsRead <= MaxInvalidatedElementsLimit) {
return escapeByStartIndexAndCount(State, Call, C.blockCount(), Buffer,
*ElemTy, *StartIndexVal,
NumCompleteOrIncompleteElementsRead);
}
}
return nullptr;
}

void StreamChecker::evalFreadFwrite(const FnDescription *Desc,
const CallEvent &Call, CheckerContext &C,
bool IsFread) const {
Expand Down Expand Up @@ -937,8 +1045,14 @@ void StreamChecker::evalFreadFwrite(const FnDescription *Desc,

// At read, invalidate the buffer in any case of error or success,
// except if EOF was already present.
if (IsFread && !E.isStreamEof())
State = escapeArgs(State, C, Call, {0});
if (IsFread && !E.isStreamEof()) {
// Try to invalidate the individual elements.
// Otherwise just fall back to invalidating the whole buffer.
ProgramStateRef InvalidatedState = tryToInvalidateFReadBufferByElements(
State, C, Call, *SizeVal, *NMembVal);
State =
InvalidatedState ? InvalidatedState : escapeArgs(State, C, Call, {0});
}

// Generate a transition for the success state.
// If we know the state to be FEOF at fread, do not add a success state.
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/StaticAnalyzer/Core/MemRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1155,10 +1155,10 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
return getSubRegion<CompoundLiteralRegion>(CL, sReg);
}

const ElementRegion*
const ElementRegion *
MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
const SubRegion* superRegion,
ASTContext &Ctx){
const SubRegion *superRegion,
const ASTContext &Ctx) {
QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();

llvm::FoldingSetNodeID ID;
Expand Down
16 changes: 16 additions & 0 deletions clang/test/AST/Interp/cxx11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,19 @@ constexpr int preInc(int x) { // both-error {{never produces a constant expressi
constexpr int postInc(int x) { // both-error {{never produces a constant expression}}
return x++; // both-note {{subexpression}}
}


namespace ReferenceToConst {
template<int n> struct S; // both-note 1{{here}}
struct LiteralType {
constexpr LiteralType(int n) : n(n) {}
int n;
};
template<int n> struct T {
T() {
static const int ki = 42;
const int &i2 = ki;
typename S<i2>::T check5; // both-error {{undefined template}}
}
};
}
5 changes: 5 additions & 0 deletions clang/test/AST/Interp/references.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,8 @@ constexpr int RecordWithRef2() {
return r.a;
}
static_assert(RecordWithRef2() == 200, "");

const char (&nonextended_string_ref)[3] = {"hi"};
static_assert(nonextended_string_ref[0] == 'h', "");
static_assert(nonextended_string_ref[1] == 'i', "");
static_assert(nonextended_string_ref[2] == '\0', "");
9 changes: 9 additions & 0 deletions clang/test/AST/Interp/vectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@ namespace {
typedef float __attribute__((vector_size(16))) VI42;
constexpr VI42 A2 = A; // expected-error {{must be initialized by a constant expression}}
}

namespace BoolToSignedIntegralCast{
typedef __attribute__((__ext_vector_type__(4))) unsigned int int4;
constexpr int4 intsT = (int4)true;
static_assert(intsT[0] == -1, "");// ref-error {{not an integral constant expression}}
static_assert(intsT[1] == -1, "");// ref-error {{not an integral constant expression}}
static_assert(intsT[2] == -1, "");// ref-error {{not an integral constant expression}}
static_assert(intsT[3] == -1, "");// ref-error {{not an integral constant expression}}
}
4 changes: 2 additions & 2 deletions clang/test/AST/ast-dump-color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ struct Invalid {
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'const Mutex &'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit constexpr[[CYAN]] Mutex[[RESET]] [[Green]]'void (Mutex &&)'[[RESET]] inline{{ .*$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'Mutex &&'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:25:3[[RESET]]> [[Yellow]]col:3[[RESET]] used[[CYAN]] mu1[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:25:3[[RESET]]> [[Yellow]]col:3[[RESET]] referenced[[CYAN]] mu1[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:18:1[[RESET]], [[Yellow]]line:25:8[[RESET]]> [[Yellow]]col:8[[RESET]][[CYAN]] mu2[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:26:1[[RESET]], [[Yellow]]col:5[[RESET]]> [[Yellow]]col:5[[RESET]][[CYAN]] TestExpr[[RESET]] [[Green]]'int'[[RESET]]
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[BLUE]]GuardedByAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:29[[RESET]], [[Yellow]]col:43[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]] non_odr_use_unevaluated{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:28:1[[RESET]], [[Yellow]]line:30:1[[RESET]]> [[Yellow]]line:28:8[[RESET]] struct[[CYAN]] Invalid[[RESET]] definition
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit referenced struct[[CYAN]] Invalid[[RESET]]
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:29:3[[RESET]], [[Yellow]]col:42[[RESET]]> [[Yellow]]col:29[[RESET]] invalid[[CYAN]] Invalid[[RESET]] [[Green]]'void (int)'[[RESET]]
Expand Down
4 changes: 2 additions & 2 deletions clang/test/AST/ast-dump-ctad-alias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ Out2<double>::AInner t(1.0);
// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0
// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible
// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2<double>::AInner' dependent
// CHECK-NEXT: | | | `-name: 'Out2<double>::AInner'
// CHECK-NEXT: | | | `-name: 'Out2<double>::AInner'
// CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}}
// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner<type-parameter-1-0>' sugar dependent
// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner<type-parameter-1-0>' dependent
// CHECK-NEXT: | | |-name: 'Inner':'Out<int>::Inner' qualified
// CHECK-NEXT: | | |-name: 'Inner':'Out<int>::Inner' qualified
// CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}}
// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0'
// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0'
Expand Down
6 changes: 3 additions & 3 deletions clang/test/AST/ast-dump-template-decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ using type2 = typename C<int>::type1<void>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:42> col:7 type2 'typename C<int>::type1<void>':'void (int)'
// CHECK-NEXT: ElaboratedType 0x{{[^ ]*}} 'typename C<int>::type1<void>' sugar
// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1<void>' sugar alias
// CHECK-NEXT: name: 'C<int>::type1':'PR55886::C<int>::type1' qualified
// CHECK-NEXT: name: 'C<int>::type1':'PR55886::C<int>::type1' qualified
// CHECK-NEXT: NestedNameSpecifier TypeSpec 'C<int>':'PR55886::C<int>'
// CHECK-NEXT: TypeAliasTemplateDecl {{.+}} type1
// CHECK-NEXT: TemplateArgument type 'void'
Expand Down Expand Up @@ -153,7 +153,7 @@ template <typename... T> struct D {
};
using t2 = D<float, char>::B<int, short>;
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B<int, short>' sugar alias{{$}}
// CHECK-NEXT: name: 'D<float, char>::B':'PR56099::D<float, char>::B' qualified
// CHECK-NEXT: name: 'D<float, char>::B':'PR56099::D<float, char>::B' qualified
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
Expand All @@ -175,7 +175,7 @@ template<class E1, class E2> class E {};
using test1 = D<E, int>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar
// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified
// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
// CHECK-NEXT: |-TemplateArgument type 'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2
Expand Down
8 changes: 4 additions & 4 deletions clang/test/AST/ast-dump-using-template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ using A = S<T>;
// CHECK: TypeAliasDecl
// CHECK-NEXT: `-ElaboratedType {{.*}} 'S<T>' sugar dependent
// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'S<T>' dependent
// CHECK-NEXT: |-name: 'S':'ns::S' qualified
// CHECK-NEXT: |-name: 'S':'ns::S' qualified
// CHECk-NEXT: | |-UsingShadowDecl {{.+}} ClassTemplate {{.+}} 'S'

// TemplateName in TemplateArgument.
Expand All @@ -30,7 +30,7 @@ using B = X<S>;
// CHECK: TypeAliasDecl
// CHECK-NEXT: `-ElaboratedType {{.*}} 'X<S>' sugar
// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'X<S>' sugar
// CHECK-NEXT: |-name: 'X' qualified
// CHECK-NEXT: |-name: 'X' qualified
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} X
// CHECK-NEXT: |-TemplateArgument template 'S':'ns::S' qualified
// CHECK-NEXT: | |-UsingShadowDecl {{.*}} implicit ClassTemplate {{.*}} 'S'
Expand All @@ -45,7 +45,7 @@ using C = decltype(DeducedTemplateSpecializationT);
// CHECK-NEXT: |-DeclRefExpr {{.*}}
// CHECK-NEXT: `-ElaboratedType {{.*}} 'S<int>' sugar
// CHECK-NEXT: `-DeducedTemplateSpecializationType {{.*}} 'ns::S<int>' sugar
// CHECK-NEXT: |-name: 'S':'ns::S' qualified
// CHECK-NEXT: |-name: 'S':'ns::S' qualified
// CHECK-NEXT: | |-UsingShadowDecl {{.+}} 'S'

S2 DeducedTemplateSpecializationT2(123);
Expand All @@ -54,5 +54,5 @@ using D = decltype(DeducedTemplateSpecializationT2);
// CHECK-NEXT: |-DeclRefExpr {{.*}}
// CHECK-NEXT: `-ElaboratedType {{.*}} 'S2<int>' sugar
// CHECK-NEXT: `-DeducedTemplateSpecializationType {{.*}} 'S2<int>' sugar
// CHECK-NEXT: |-name: 'S2':'ns::S2' qualified
// CHECK-NEXT: |-name: 'S2':'ns::S2' qualified
//CHECk-NEXT: | |-UsingShadowDecl {{.+}} ClassTemplate {{.+}} 'S2'
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
// suppressed.
#pragma clang system_header

typedef __typeof(sizeof(int)) size_t;
typedef struct _FILE {
unsigned char *_p;
} FILE;
FILE *fopen(const char *restrict, const char *restrict) __asm("_" "fopen" );
int fputc(int, FILE *);
int fputs(const char *restrict, FILE *restrict) __asm("_" "fputs" );
size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
int fgetc(FILE *stream);
int fclose(FILE *);
void exit(int);

Expand Down
445 changes: 445 additions & 0 deletions clang/test/Analysis/fread.c

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions clang/test/C/drs/dr1xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ void dr126(void) {
*/
*object = 12; /* ok */
++object; /* expected-error {{cannot assign to variable 'object' with const-qualified type 'const IP' (aka 'int *const')}} */
/* expected-note@-1 {{add '*' to dereference it}} */
}

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

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

// CHECK-LABEL: @plusnosimd() #16
// 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
__attribute__((target("+nosimd")))
void plusnosimd() {}
// CHECK-LABEL: @nosimd() #16
// CHECK-LABEL: @noneon() #17
__attribute__((target("no-neon")))
void noneon() {}
// CHECK-LABEL: @nosimd() #17
__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() #17
// CHECK-LABEL: @minusarch() #18
__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,+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 #3 = { {{.*}} "target-features"="+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+ras,+rcpc,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" }
// CHECK: attributes #4 = { {{.*}} "target-cpu"="cortex-a710" "target-features"="+bf16,+complxnum,+crc,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+ras,+rcpc,+rdm,+sb,+sve,+sve2,+sve2-bitperm" }
// CHECK: attributes #5 = { {{.*}} "tune-cpu"="cortex-a710" }
// CHECK: attributes #6 = { {{.*}} "target-cpu"="generic" }
// CHECK: attributes #7 = { {{.*}} "tune-cpu"="generic" }
// CHECK: attributes #8 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+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" }
// 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" }
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,+fp-armv8,+fp16fml,+fullfp16,+neon,+rand,-v9.5a" }
// 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 #[[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"="+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 #[[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 #[[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"="+fp-armv8,+fullfp16,+neon,-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 #[[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,+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 #[[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 #[[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"="+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 #[[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 #[[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,+fp-armv8,+jsconv,+neon,-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 #[[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,+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 #[[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 #[[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"="+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: 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-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
16 changes: 9 additions & 7 deletions clang/test/CodeGenCUDA/managed-var.cu
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,10 @@ __device__ __host__ float load2() {

// HOST-LABEL: define {{.*}}@_Z5load3v()
// HOST: %ld.managed = load ptr, ptr @v2, align 16
// HOST: %0 = getelementptr inbounds [100 x %struct.vec], ptr %ld.managed, i64 0, i64 1, i32 1
// HOST: %1 = load float, ptr %0, align 4
// HOST: ret float %1
// HOST: %0 = getelementptr inbounds [100 x %struct.vec], ptr %ld.managed, i64 0, i64 1
// HOST: %1 = getelementptr inbounds %struct.vec, ptr %0, i32 0, i32 1
// HOST: %2 = load float, ptr %1, align 4
// HOST: ret float %2
float load3() {
return v2[1].y;
}
Expand All @@ -139,10 +140,11 @@ float load3() {
// HOST: %0 = getelementptr inbounds [100 x %struct.vec], ptr %ld.managed, i64 0, i64 1
// HOST: %1 = ptrtoint ptr %0 to i64
// HOST: %ld.managed1 = load ptr, ptr @v2, align 16
// HOST: %2 = getelementptr inbounds [100 x %struct.vec], ptr %ld.managed1, i64 0, i64 1, i32 1
// HOST: %3 = ptrtoint ptr %2 to i64
// HOST: %4 = sub i64 %3, %1
// HOST: %sub.ptr.div = sdiv exact i64 %4, 4
// HOST: %2 = getelementptr inbounds [100 x %struct.vec], ptr %ld.managed1, i64 0, i64 1
// HOST: %3 = getelementptr inbounds %struct.vec, ptr %2, i32 0, i32 1
// HOST: %4 = ptrtoint ptr %3 to i64
// HOST: %5 = sub i64 %4, %1
// HOST: %sub.ptr.div = sdiv exact i64 %5, 4
// HOST: %conv = sitofp i64 %sub.ptr.div to float
// HOST: ret float %conv
float addr_taken2() {
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/2011-12-19-init-list-ctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ struct S {
// CHECK: store i32 0, ptr @arr
// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (%struct.S, ptr @arr, i32 0, i32 1), ptr noundef @.str)
// CHECK: store i32 1, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 1)
// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (%struct.S, ptr @arr, i64 1, i32 1), ptr noundef @.str.1)
// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (%struct.S, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 1), i32 0, i32 1), ptr noundef @.str.1)
// CHECK: store i32 2, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 2)
// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (%struct.S, ptr @arr, i64 2, i32 1), ptr noundef @.str.2)
// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (%struct.S, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 2), i32 0, i32 1), ptr noundef @.str.2)
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ std::initializer_list<std::initializer_list<int>> nested = {
// CHECK-DYNAMIC-BL: store i32 {{.*}}, ptr getelementptr inbounds (i32, ptr @_ZGR6nested1_, i64 1)
// CHECK-DYNAMIC-BL: store ptr @_ZGR6nested1_,
// CHECK-DYNAMIC-BL: ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 1), align 8
// CHECK-DYNAMIC-BL: store i64 2, ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 1, i32 1), align 8
// CHECK-DYNAMIC-BL: store i64 2, ptr getelementptr inbounds ({{.*}}, ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 1), i32 0, i32 1), align 8
// CHECK-DYNAMIC-BL: store i32 5, ptr @_ZGR6nested2_
// CHECK-DYNAMIC-BL: store i32 {{.*}}, ptr getelementptr inbounds (i32, ptr @_ZGR6nested2_, i64 1)
// CHECK-DYNAMIC-BL: store ptr @_ZGR6nested2_,
// CHECK-DYNAMIC-BL: ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 2), align 8
// CHECK-DYNAMIC-BL: store i64 2, ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 2, i32 1), align 8
// CHECK-DYNAMIC-BL: store i64 2, ptr getelementptr inbounds ({{.*}}, ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 2), i32 0, i32 1), align 8
// CHECK-DYNAMIC-BL: store ptr @_ZGR6nested_,
// CHECK-DYNAMIC-BL: ptr @nested, align 8
// CHECK-DYNAMIC-BL: store i64 3, ptr getelementptr inbounds ({{.*}}, ptr @nested, i32 0, i32 1), align 8
Expand Down Expand Up @@ -119,13 +119,13 @@ std::initializer_list<std::initializer_list<int>> nested = {
// CHECK-DYNAMIC-BE: store ptr @_ZGR6nested1_,
// CHECK-DYNAMIC-BE: ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 1), align 8
// CHECK-DYNAMIC-BE: store ptr getelementptr inbounds ([2 x i32], ptr @_ZGR6nested1_, i64 0, i64 2),
// CHECK-DYNAMIC-BE: ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 1, i32 1), align 8
// CHECK-DYNAMIC-BE: ptr getelementptr inbounds ({{.*}}, ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 1), i32 0, i32 1), align 8
// CHECK-DYNAMIC-BE: store i32 5, ptr @_ZGR6nested2_
// CHECK-DYNAMIC-BE: store i32 {{.*}}, ptr getelementptr inbounds (i32, ptr @_ZGR6nested2_, i64 1)
// CHECK-DYNAMIC-BE: store ptr @_ZGR6nested2_,
// CHECK-DYNAMIC-BE: ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 2), align 8
// CHECK-DYNAMIC-BE: store ptr getelementptr inbounds ([2 x i32], ptr @_ZGR6nested2_, i64 0, i64 2),
// CHECK-DYNAMIC-BE: ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 2, i32 1), align 8
// CHECK-DYNAMIC-BE: ptr getelementptr inbounds ({{.*}}, ptr getelementptr inbounds ({{.*}}, ptr @_ZGR6nested_, i64 2), i32 0, i32 1), align 8
// CHECK-DYNAMIC-BE: store ptr @_ZGR6nested_,
// CHECK-DYNAMIC-BE: ptr @nested, align 8
// CHECK-DYNAMIC-BE: store ptr getelementptr inbounds ([3 x {{.*}}], ptr @_ZGR6nested_, i64 0, i64 3),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,12 +365,12 @@ namespace partly_constant {
//
// Second init list.
// CHECK: store ptr {{.*}}@[[PARTLY_CONSTANT_SECOND]]{{.*}}, ptr getelementptr inbounds ({{.*}}, ptr {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 1)
// CHECK: store i64 2, ptr getelementptr inbounds ({{.*}}, ptr {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 1, i32 1)
// CHECK: store i64 2, ptr getelementptr inbounds ({{.*}}, ptr getelementptr inbounds ({{.*}}, ptr {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 1), i32 0, i32 1)
//
// Third init list.
// CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
// CHECK: store ptr {{.*}}@[[PARTLY_CONSTANT_THIRD]]{{.*}}, ptr getelementptr inbounds ({{.*}}, ptr {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 2)
// CHECK: store i64 4, ptr getelementptr inbounds ({{.*}}, ptr {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 2, i32 1)
// CHECK: store i64 4, ptr getelementptr inbounds ({{.*}}, ptr getelementptr inbounds ({{.*}}, ptr {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 2), i32 0, i32 1)
// CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
//
// Outer init list.
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/ms-inline-asm-fields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extern "C" int test_param_field(A p) {

extern "C" int test_namespace_global() {
// CHECK: define{{.*}} i32 @test_namespace_global()
// CHECK: call i32 asm sideeffect inteldialect "mov eax, $1", "{{.*}}"(ptr elementtype(i32) getelementptr inbounds (%struct.A, ptr @_ZN4asdf8a_globalE, i32 0, i32 2, i32 1))
// CHECK: call i32 asm sideeffect inteldialect "mov eax, $1", "{{.*}}"(ptr elementtype(i32) getelementptr inbounds (%"struct.A::B", ptr getelementptr inbounds (%struct.A, ptr @_ZN4asdf8a_globalE, i32 0, i32 2), i32 0, i32 1))
// CHECK: ret i32
__asm mov eax, asdf::a_global.a3.b2
}
Expand Down
Loading