Original file line number Diff line number Diff line change
Expand Up @@ -339,17 +339,6 @@ void setHasValue(RecordStorageLocation &OptionalLoc, BoolValue &HasValueVal,
Env.setValue(locForHasValue(OptionalLoc), HasValueVal);
}

/// Creates a symbolic value for an `optional` value at an existing storage
/// location. Uses `HasValueVal` as the symbolic value of the "has_value"
/// property.
RecordValue &createOptionalValue(RecordStorageLocation &Loc,
BoolValue &HasValueVal, Environment &Env) {
auto &OptionalVal = Env.create<RecordValue>(Loc);
Env.setValue(Loc, OptionalVal);
setHasValue(Loc, HasValueVal, Env);
return OptionalVal;
}

/// Returns the symbolic value that represents the "has_value" property of the
/// optional at `OptionalLoc`. Returns null if `OptionalLoc` is null.
BoolValue *getHasValue(Environment &Env, RecordStorageLocation *OptionalLoc) {
Expand Down Expand Up @@ -413,9 +402,8 @@ void transferArrowOpCall(const Expr *UnwrapExpr, const Expr *ObjectExpr,
void transferMakeOptionalCall(const CallExpr *E,
const MatchFinder::MatchResult &,
LatticeTransferState &State) {
State.Env.setValue(
*E, createOptionalValue(State.Env.getResultObjectLocation(*E),
State.Env.getBoolLiteralValue(true), State.Env));
setHasValue(State.Env.getResultObjectLocation(*E),
State.Env.getBoolLiteralValue(true), State.Env);
}

void transferOptionalHasValueCall(const CXXMemberCallExpr *CallExpr,
Expand Down Expand Up @@ -483,9 +471,6 @@ void transferValueOrNotEqX(const Expr *ComparisonExpr,
void transferCallReturningOptional(const CallExpr *E,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) {
if (State.Env.getValue(*E) != nullptr)
return;

RecordStorageLocation *Loc = nullptr;
if (E->isPRValue()) {
Loc = &State.Env.getResultObjectLocation(*E);
Expand All @@ -497,16 +482,16 @@ void transferCallReturningOptional(const CallExpr *E,
}
}

RecordValue &Val =
createOptionalValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env);
if (E->isPRValue())
State.Env.setValue(*E, Val);
if (State.Env.getValue(locForHasValue(*Loc)) != nullptr)
return;

setHasValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env);
}

void constructOptionalValue(const Expr &E, Environment &Env,
BoolValue &HasValueVal) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(E);
Env.setValue(E, createOptionalValue(Loc, HasValueVal, Env));
setHasValue(Loc, HasValueVal, Env);
}

/// Returns a symbolic value for the "has_value" property of an `optional<T>`
Expand Down Expand Up @@ -555,7 +540,7 @@ void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal,
assert(E->getNumArgs() > 0);

if (auto *Loc = State.Env.get<RecordStorageLocation>(*E->getArg(0))) {
createOptionalValue(*Loc, HasValueVal, State.Env);
setHasValue(*Loc, HasValueVal, State.Env);

// Assign a storage location for the whole expression.
State.Env.setStorageLocation(*E, *Loc);
Expand Down Expand Up @@ -587,11 +572,11 @@ void transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2,

if (Loc1 == nullptr) {
if (Loc2 != nullptr)
createOptionalValue(*Loc2, Env.makeAtomicBoolValue(), Env);
setHasValue(*Loc2, Env.makeAtomicBoolValue(), Env);
return;
}
if (Loc2 == nullptr) {
createOptionalValue(*Loc1, Env.makeAtomicBoolValue(), Env);
setHasValue(*Loc1, Env.makeAtomicBoolValue(), Env);
return;
}

Expand All @@ -609,8 +594,8 @@ void transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2,
if (BoolVal2 == nullptr)
BoolVal2 = &Env.makeAtomicBoolValue();

createOptionalValue(*Loc1, *BoolVal2, Env);
createOptionalValue(*Loc2, *BoolVal1, Env);
setHasValue(*Loc1, *BoolVal2, Env);
setHasValue(*Loc2, *BoolVal1, Env);
}

void transferSwapCall(const CXXMemberCallExpr *E,
Expand Down Expand Up @@ -806,8 +791,7 @@ auto buildTransferMatchSwitch() {
LatticeTransferState &State) {
if (RecordStorageLocation *Loc =
getImplicitObjectLocation(*E, State.Env)) {
createOptionalValue(*Loc, State.Env.getBoolLiteralValue(true),
State.Env);
setHasValue(*Loc, State.Env.getBoolLiteralValue(true), State.Env);
}
})

Expand All @@ -818,8 +802,8 @@ auto buildTransferMatchSwitch() {
LatticeTransferState &State) {
if (RecordStorageLocation *Loc =
getImplicitObjectLocation(*E, State.Env)) {
createOptionalValue(*Loc, State.Env.getBoolLiteralValue(false),
State.Env);
setHasValue(*Loc, State.Env.getBoolLiteralValue(false),
State.Env);
}
})

Expand Down
3 changes: 0 additions & 3 deletions clang/lib/Analysis/FlowSensitive/RecordOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst,
copySyntheticField(SrcFieldLoc->getType(), *SrcFieldLoc,
Dst.getSyntheticField(Name), Env);
}

RecordValue *DstVal = &Env.create<RecordValue>(Dst);
Env.setValue(Dst, *DstVal);
}

bool recordsEqual(const RecordStorageLocation &Loc1, const Environment &Env1,
Expand Down
62 changes: 21 additions & 41 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ static Value *maybeUnpackLValueExpr(const Expr &E, Environment &Env) {
}

static void propagateValue(const Expr &From, const Expr &To, Environment &Env) {
if (From.getType()->isRecordType())
return;
if (auto *Val = Env.getValue(From))
Env.setValue(To, *Val);
}
Expand Down Expand Up @@ -403,6 +405,9 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
return;

if (Ret->isPRValue()) {
if (Ret->getType()->isRecordType())
return;

auto *Val = Env.getValue(*Ret);
if (Val == nullptr)
return;
Expand Down Expand Up @@ -457,15 +462,9 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
assert(ArgExpr != nullptr);
propagateValueOrStorageLocation(*ArgExpr, *S, Env);

// If this is a prvalue of record type, we consider it to be an "original
// record constructor", which we always require to have a `RecordValue`.
// So make sure we have a value if we didn't propagate one above.
if (S->isPRValue() && S->getType()->isRecordType()) {
if (Env.getValue(*S) == nullptr) {
auto &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
refreshRecordValue(Loc, Env);
}
auto &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
}
}

Expand Down Expand Up @@ -495,7 +494,6 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}

RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.setValue(*S, refreshRecordValue(Loc, Env));

if (ConstructorDecl->isCopyOrMoveConstructor()) {
// It is permissible for a copy/move constructor to have additional
Expand Down Expand Up @@ -542,8 +540,7 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {

RecordStorageLocation *LocSrc = nullptr;
if (Arg1->isPRValue()) {
if (auto *Val = Env.get<RecordValue>(*Arg1))
LocSrc = &Val->getLoc();
LocSrc = &Env.getResultObjectLocation(*Arg1);
} else {
LocSrc = Env.get<RecordStorageLocation>(*Arg1);
}
Expand Down Expand Up @@ -575,15 +572,6 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
propagateValue(*RBO->getSemanticForm(), *RBO, Env);
}

void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
if (S->getCastKind() == CK_ConstructorConversion) {
const Expr *SubExpr = S->getSubExpr();
assert(SubExpr != nullptr);

propagateValue(*SubExpr, *S, Env);
}
}

void VisitCallExpr(const CallExpr *S) {
// Of clang's builtins, only `__builtin_expect` is handled explicitly, since
// others (like trap, debugtrap, and unreachable) are handled by CFG
Expand Down Expand Up @@ -613,31 +601,27 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {

// If this call produces a prvalue of record type, initialize its fields
// with values.
if (S->getType()->isRecordType() && S->isPRValue())
if (Env.getValue(*S) == nullptr) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
Env.setValue(*S, refreshRecordValue(Loc, Env));
}
if (S->getType()->isRecordType() && S->isPRValue()) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
}
}
}

void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
const Expr *SubExpr = S->getSubExpr();
assert(SubExpr != nullptr);

Value *SubExprVal = Env.getValue(*SubExpr);
if (SubExprVal == nullptr)
return;
StorageLocation &Loc = Env.createStorageLocation(*S);
Env.setStorageLocation(*S, Loc);

if (RecordValue *RecordVal = dyn_cast<RecordValue>(SubExprVal)) {
Env.setStorageLocation(*S, RecordVal->getLoc());
if (SubExpr->getType()->isRecordType())
// Nothing else left to do -- we initialized the record when transferring
// `SubExpr`.
return;
}

StorageLocation &Loc = Env.createStorageLocation(*S);
Env.setValue(Loc, *SubExprVal);
Env.setStorageLocation(*S, Loc);
if (Value *SubExprVal = Env.getValue(*SubExpr))
Env.setValue(Loc, *SubExprVal);
}

void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
Expand Down Expand Up @@ -683,15 +667,11 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
return;
}

// In case the initializer list is transparent, we just need to propagate
// the value that it contains.
if (S->isSemanticForm() && S->isTransparent()) {
propagateValue(*S->getInit(0), *S, Env);
// If the initializer list is transparent, there's nothing to do.
if (S->isSemanticForm() && S->isTransparent())
return;
}

RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.setValue(*S, refreshRecordValue(Loc, Env));

// Initialization of base classes and fields of record type happens when we
// visit the nested `CXXConstructExpr` or `InitListExpr` for that base class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,11 @@ builtinTransferInitializer(const CFGInitializer &Elt,
return;

ParentLoc->setChild(*Member, InitExprLoc);
} else if (auto *InitExprVal = Env.getValue(*InitExpr)) {
assert(MemberLoc != nullptr);
// Record-type initializers construct themselves directly into the result
// object, so there is no need to handle them here.
if (!Member->getType()->isRecordType())
} else if (!Member->getType()->isRecordType()) {
assert(MemberLoc != nullptr);
if (auto *InitExprVal = Env.getValue(*InitExpr))
Env.setValue(*MemberLoc, *InitExprVal);
}
}
Expand Down
2 changes: 0 additions & 2 deletions clang/lib/Analysis/FlowSensitive/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ raw_ostream &operator<<(raw_ostream &OS, const Value &Val) {
return OS << "Integer(@" << &Val << ")";
case Value::Kind::Pointer:
return OS << "Pointer(" << &cast<PointerValue>(Val).getPointeeLoc() << ")";
case Value::Kind::Record:
return OS << "Record(" << &cast<RecordValue>(Val).getLoc() << ")";
case Value::Kind::TopBool:
return OS << "TopBool(" << cast<TopBoolValue>(Val).getAtom() << ")";
case Value::Kind::AtomicBool:
Expand Down
31 changes: 23 additions & 8 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,15 @@ struct BinOpInfo {
return UnOp->getSubExpr()->getType()->isFixedPointType();
return false;
}

/// Check if the RHS has a signed integer representation.
bool rhsHasSignedIntegerRepresentation() const {
if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) {
QualType RHSType = BinOp->getRHS()->getType();
return RHSType->hasSignedIntegerRepresentation();
}
return false;
}
};

static bool MustVisitNullValue(const Expr *E) {
Expand Down Expand Up @@ -782,7 +791,7 @@ class ScalarExprEmitter
void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops,
llvm::Value *Zero,bool isDiv);
// Common helper for getting how wide LHS of shift is.
static Value *GetMaximumShiftAmount(Value *LHS, Value *RHS);
static Value *GetMaximumShiftAmount(Value *LHS, Value *RHS, bool RHSIsSigned);

// Used for shifting constraints for OpenCL, do mask for powers of 2, URem for
// non powers of two.
Expand Down Expand Up @@ -4344,7 +4353,8 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
return Builder.CreateExactSDiv(diffInChars, divisor, "sub.ptr.div");
}

Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS) {
Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS,
bool RHSIsSigned) {
llvm::IntegerType *Ty;
if (llvm::VectorType *VT = dyn_cast<llvm::VectorType>(LHS->getType()))
Ty = cast<llvm::IntegerType>(VT->getElementType());
Expand All @@ -4355,7 +4365,9 @@ Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS) {
// this in ConstantInt::get, this results in the value getting truncated.
// Constrain the return value to be max(RHS) in this case.
llvm::Type *RHSTy = RHS->getType();
llvm::APInt RHSMax = llvm::APInt::getMaxValue(RHSTy->getScalarSizeInBits());
llvm::APInt RHSMax =
RHSIsSigned ? llvm::APInt::getSignedMaxValue(RHSTy->getScalarSizeInBits())
: llvm::APInt::getMaxValue(RHSTy->getScalarSizeInBits());
if (RHSMax.ult(Ty->getBitWidth()))
return llvm::ConstantInt::get(RHSTy, RHSMax);
return llvm::ConstantInt::get(RHSTy, Ty->getBitWidth() - 1);
Expand All @@ -4370,7 +4382,7 @@ Value *ScalarExprEmitter::ConstrainShiftValue(Value *LHS, Value *RHS,
Ty = cast<llvm::IntegerType>(LHS->getType());

if (llvm::isPowerOf2_64(Ty->getBitWidth()))
return Builder.CreateAnd(RHS, GetMaximumShiftAmount(LHS, RHS), Name);
return Builder.CreateAnd(RHS, GetMaximumShiftAmount(LHS, RHS, false), Name);

return Builder.CreateURem(
RHS, llvm::ConstantInt::get(RHS->getType(), Ty->getBitWidth()), Name);
Expand Down Expand Up @@ -4403,7 +4415,9 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
SmallVector<std::pair<Value *, SanitizerMask>, 2> Checks;
llvm::Value *WidthMinusOne = GetMaximumShiftAmount(Ops.LHS, Ops.RHS);
bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation();
llvm::Value *WidthMinusOne =
GetMaximumShiftAmount(Ops.LHS, Ops.RHS, RHSIsSigned);
llvm::Value *ValidExponent = Builder.CreateICmpULE(Ops.RHS, WidthMinusOne);

if (SanitizeExponent) {
Expand All @@ -4421,7 +4435,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
Builder.CreateCondBr(ValidExponent, CheckShiftBase, Cont);
llvm::Value *PromotedWidthMinusOne =
(RHS == Ops.RHS) ? WidthMinusOne
: GetMaximumShiftAmount(Ops.LHS, RHS);
: GetMaximumShiftAmount(Ops.LHS, RHS, RHSIsSigned);
CGF.EmitBlock(CheckShiftBase);
llvm::Value *BitsShiftedOff = Builder.CreateLShr(
Ops.LHS, Builder.CreateSub(PromotedWidthMinusOne, RHS, "shl.zeros",
Expand Down Expand Up @@ -4471,8 +4485,9 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
llvm::Value *Valid =
Builder.CreateICmpULE(Ops.RHS, GetMaximumShiftAmount(Ops.LHS, Ops.RHS));
bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation();
llvm::Value *Valid = Builder.CreateICmpULE(
Ops.RHS, GetMaximumShiftAmount(Ops.LHS, Ops.RHS, RHSIsSigned));
EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::ShiftExponent), Ops);
}

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CGLoopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,8 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
setPipelineDisabled(true);
break;
case LoopHintAttr::UnrollCount:
setUnrollState(LoopAttributes::Disable);
break;
case LoopHintAttr::UnrollAndJamCount:
case LoopHintAttr::VectorizeWidth:
case LoopHintAttr::InterleaveCount:
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2011,11 +2011,13 @@ struct CounterCoverageMappingBuilder
Counter TrueCount = llvm::EnableSingleByteCoverage
? getRegionCounter(E->getTrueExpr())
: getRegionCounter(E);

propagateCounts(ParentCount, E->getCond());
Counter OutCount;

if (!isa<BinaryConditionalOperator>(E)) {
if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
propagateCounts(ParentCount, BCO->getCommon());
OutCount = TrueCount;
} else {
propagateCounts(ParentCount, E->getCond());
// The 'then' count applies to the area immediately after the condition.
auto Gap =
findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
Expand All @@ -2024,8 +2026,6 @@ struct CounterCoverageMappingBuilder

extendRegion(E->getTrueExpr());
OutCount = propagateCounts(TrueCount, E->getTrueExpr());
} else {
OutCount = TrueCount;
}

extendRegion(E->getFalseExpr());
Expand Down
54 changes: 38 additions & 16 deletions clang/lib/Driver/OffloadBundler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1010,13 +1010,19 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,

uint16_t CompressionMethod = static_cast<uint16_t>(P.format);
uint32_t UncompressedSize = Input.getBuffer().size();
uint32_t TotalFileSize = MagicNumber.size() + sizeof(TotalFileSize) +
sizeof(Version) + sizeof(CompressionMethod) +
sizeof(UncompressedSize) + sizeof(TruncatedHash) +
CompressedBuffer.size();

SmallVector<char, 0> FinalBuffer;
llvm::raw_svector_ostream OS(FinalBuffer);
OS << MagicNumber;
OS.write(reinterpret_cast<const char *>(&Version), sizeof(Version));
OS.write(reinterpret_cast<const char *>(&CompressionMethod),
sizeof(CompressionMethod));
OS.write(reinterpret_cast<const char *>(&TotalFileSize),
sizeof(TotalFileSize));
OS.write(reinterpret_cast<const char *>(&UncompressedSize),
sizeof(UncompressedSize));
OS.write(reinterpret_cast<const char *>(&TruncatedHash),
Expand All @@ -1034,6 +1040,8 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,
(UncompressedSize / (1024.0 * 1024.0)) / CompressionTimeSeconds;

llvm::errs() << "Compressed bundle format version: " << Version << "\n"
<< "Total file size (including headers): "
<< formatWithCommas(TotalFileSize) << " bytes\n"
<< "Compression method used: " << MethodUsed << "\n"
<< "Compression level: " << P.level << "\n"
<< "Binary size before compression: "
Expand All @@ -1059,31 +1067,42 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,

StringRef Blob = Input.getBuffer();

if (Blob.size() < HeaderSize) {
if (Blob.size() < V1HeaderSize)
return llvm::MemoryBuffer::getMemBufferCopy(Blob);
}

if (llvm::identify_magic(Blob) !=
llvm::file_magic::offload_bundle_compressed) {
if (Verbose)
llvm::errs() << "Uncompressed bundle.\n";
return llvm::MemoryBuffer::getMemBufferCopy(Blob);
}

size_t CurrentOffset = MagicSize;

uint16_t ThisVersion;
memcpy(&ThisVersion, Blob.data() + CurrentOffset, sizeof(uint16_t));
CurrentOffset += VersionFieldSize;

uint16_t CompressionMethod;
memcpy(&CompressionMethod, Blob.data() + CurrentOffset, sizeof(uint16_t));
CurrentOffset += MethodFieldSize;

uint32_t TotalFileSize;
if (ThisVersion >= 2) {
if (Blob.size() < V2HeaderSize)
return createStringError(inconvertibleErrorCode(),
"Compressed bundle header size too small");
memcpy(&TotalFileSize, Blob.data() + CurrentOffset, sizeof(uint32_t));
CurrentOffset += FileSizeFieldSize;
}

uint32_t UncompressedSize;
memcpy(&UncompressedSize, Blob.data() + CurrentOffset, sizeof(uint32_t));
CurrentOffset += UncompressedSizeFieldSize;

uint64_t StoredHash;
memcpy(&ThisVersion, Input.getBuffer().data() + MagicNumber.size(),
sizeof(uint16_t));
memcpy(&CompressionMethod, Blob.data() + MagicSize + VersionFieldSize,
sizeof(uint16_t));
memcpy(&UncompressedSize,
Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize,
sizeof(uint32_t));
memcpy(&StoredHash,
Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize +
SizeFieldSize,
sizeof(uint64_t));
memcpy(&StoredHash, Blob.data() + CurrentOffset, sizeof(uint64_t));
CurrentOffset += HashFieldSize;

llvm::compression::Format CompressionFormat;
if (CompressionMethod ==
Expand All @@ -1102,7 +1121,7 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
DecompressTimer.startTimer();

SmallVector<uint8_t, 0> DecompressedData;
StringRef CompressedData = Blob.substr(HeaderSize);
StringRef CompressedData = Blob.substr(CurrentOffset);
if (llvm::Error DecompressionError = llvm::compression::decompress(
CompressionFormat, llvm::arrayRefFromStringRef(CompressedData),
DecompressedData, UncompressedSize))
Expand Down Expand Up @@ -1135,8 +1154,11 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
double DecompressionSpeedMBs =
(UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds;

llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n"
<< "Decompression method: "
llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n";
if (ThisVersion >= 2)
llvm::errs() << "Total file size (from header): "
<< formatWithCommas(TotalFileSize) << " bytes\n";
llvm::errs() << "Decompression method: "
<< (CompressionFormat == llvm::compression::Format::Zlib
? "zlib"
: "zstd")
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2116,8 +2116,12 @@ unsigned tools::getDwarfVersion(const ToolChain &TC,
const llvm::opt::ArgList &Args) {
unsigned DwarfVersion = ParseDebugDefaultVersion(TC, Args);
if (const Arg *GDwarfN = getDwarfNArg(Args))
if (int N = DwarfVersionNum(GDwarfN->getSpelling()))
if (int N = DwarfVersionNum(GDwarfN->getSpelling())) {
DwarfVersion = N;
if (DwarfVersion == 5 && TC.getTriple().isOSAIX())
TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
<< GDwarfN->getSpelling() << TC.getTriple().str();
}
if (DwarfVersion == 0) {
DwarfVersion = TC.GetDefaultDwarfVersion();
assert(DwarfVersion && "toolchain default DWARF version must be nonzero");
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3660,6 +3660,9 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
case LangOptions::ClangABI::Ver17:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");
break;
case LangOptions::ClangABI::Ver18:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0");
break;
case LangOptions::ClangABI::Latest:
break;
}
Expand Down Expand Up @@ -4167,6 +4170,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
else if (Major <= 17)
Opts.setClangABICompat(LangOptions::ClangABI::Ver17);
else if (Major <= 18)
Opts.setClangABICompat(LangOptions::ClangABI::Ver18);
} else if (Ver != "latest") {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Headers/avxintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,7 @@ _mm256_permutevar_pd(__m256d __a, __m256i __c)

/// Copies the values stored in a 128-bit vector of [4 x float] as
/// specified by the 128-bit integer vector operand.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VPERMILPS </c> instruction.
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Parse/ParsePragma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1569,7 +1569,8 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
ConsumeToken(); // Consume the constant expression eof terminator.

if (Arg2Error || R.isInvalid() ||
Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),
/*AllowZero=*/false))
return false;

// Argument is a constant expression with an integer type.
Expand All @@ -1594,7 +1595,8 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
ConsumeToken(); // Consume the constant expression eof terminator.

if (R.isInvalid() ||
Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),
/*AllowZero=*/true))
return false;

// Argument is a constant expression with an integer type.
Expand Down
36 changes: 30 additions & 6 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3507,11 +3507,15 @@ bool Sema::ParseSVEImmChecks(
static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) {
if (FD->hasAttr<ArmLocallyStreamingAttr>())
return ArmStreaming;
if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
return ArmStreaming;
if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask)
return ArmStreamingCompatible;
if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
if (FPT->getAArch64SMEAttributes() &
FunctionType::SME_PStateSMEnabledMask)
return ArmStreaming;
if (FPT->getAArch64SMEAttributes() &
FunctionType::SME_PStateSMCompatibleMask)
return ArmStreamingCompatible;
}
}
return ArmNonStreaming;
}
Expand Down Expand Up @@ -7949,6 +7953,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
// For variadic functions, we may have more args than parameters.
// For some K&R functions, we may have less args than parameters.
const auto N = std::min<unsigned>(Proto->getNumParams(), Args.size());
bool AnyScalableArgsOrRet = Proto->getReturnType()->isSizelessVectorType();
for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
if (const Expr *Arg = Args[ArgIdx]) {
Expand All @@ -7962,6 +7967,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
checkAIXMemberAlignment((Arg->getExprLoc()), Arg);

QualType ParamTy = Proto->getParamType(ArgIdx);
if (ParamTy->isSizelessVectorType())
AnyScalableArgsOrRet = true;
QualType ArgTy = Arg->getType();
CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
ArgTy, ParamTy);
Expand All @@ -7982,6 +7989,23 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
}
}

// If the call requires a streaming-mode change and has scalable vector
// arguments or return values, then warn the user that the streaming and
// non-streaming vector lengths may be different.
const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext);
if (CallerFD && (!FD || !FD->getBuiltinID()) && AnyScalableArgsOrRet) {
bool IsCalleeStreaming =
ExtInfo.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask;
bool IsCalleeStreamingCompatible =
ExtInfo.AArch64SMEAttributes &
FunctionType::SME_PStateSMCompatibleMask;
ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
if (!IsCalleeStreamingCompatible &&
(CallerFnType == ArmStreamingCompatible ||
((CallerFnType == ArmStreaming) ^ IsCalleeStreaming)))
Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming);
}

FunctionType::ArmStateValue CalleeArmZAState =
FunctionType::getArmZAState(ExtInfo.AArch64SMEAttributes);
FunctionType::ArmStateValue CalleeArmZT0State =
Expand All @@ -7990,7 +8014,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
CalleeArmZT0State != FunctionType::ARM_None) {
bool CallerHasZAState = false;
bool CallerHasZT0State = false;
if (const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) {
if (CallerFD) {
auto *Attr = CallerFD->getAttr<ArmNewAttr>();
if (Attr && Attr->isNewZA())
CallerHasZAState = true;
Expand Down
12 changes: 11 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12408,12 +12408,22 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}

// Check if the function definition uses any AArch64 SME features without
// having the '+sme' feature enabled.
// having the '+sme' feature enabled and warn user if sme locally streaming
// function returns or uses arguments with VL-based types.
if (DeclIsDefn) {
const auto *Attr = NewFD->getAttr<ArmNewAttr>();
bool UsesSM = NewFD->hasAttr<ArmLocallyStreamingAttr>();
bool UsesZA = Attr && Attr->isNewZA();
bool UsesZT0 = Attr && Attr->isNewZT0();

if (NewFD->hasAttr<ArmLocallyStreamingAttr>()) {
if (NewFD->getReturnType()->isSizelessVectorType() ||
llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) {
return P->getOriginalType()->isSizelessVectorType();
}))
Diag(NewFD->getLocation(),
diag::warn_sme_locally_streaming_has_vl_args_returns);
}
if (const auto *FPT = NewFD->getType()->getAs<FunctionProtoType>()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
UsesSM |=
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3902,7 +3902,7 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal,
return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc);
}

bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) {
bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc, bool AllowZero) {
assert(E && "Invalid expression");

if (E->isValueDependent())
Expand All @@ -3920,7 +3920,13 @@ bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) {
if (R.isInvalid())
return true;

bool ValueIsPositive = ValueAPS.isStrictlyPositive();
// GCC allows the value of unroll count to be 0.
// https://gcc.gnu.org/onlinedocs/gcc/Loop-Specific-Pragmas.html says
// "The values of 0 and 1 block any unrolling of the loop."
// The values doesn't have to be strictly positive in '#pragma GCC unroll' and
// '#pragma unroll' cases.
bool ValueIsPositive =
AllowZero ? ValueAPS.isNonNegative() : ValueAPS.isStrictlyPositive();
if (!ValueIsPositive || ValueAPS.getActiveBits() > 31) {
Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_value)
<< toString(ValueAPS, 10) << ValueIsPositive;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,10 @@ Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) {
}
}

// Anything exported from a module should never be considered unused.
for (auto *Exported : ED->decls())
Exported->markUsed(getASTContext());

return D;
}

Expand Down
21 changes: 16 additions & 5 deletions clang/lib/Sema/SemaStmtAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,18 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable);
} else if (PragmaName == "unroll") {
// #pragma unroll N
if (ValueExpr)
SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric);
else
if (ValueExpr) {
llvm::APSInt ValueAPS;
ExprResult R = S.VerifyIntegerConstantExpression(ValueExpr, &ValueAPS);
assert(!R.isInvalid() && "unroll count value must be a valid value, it's "
"should be checked in Sema::CheckLoopHintExpr");
(void)R;
// The values of 0 and 1 block any unrolling of the loop.
if (ValueAPS.isZero() || ValueAPS.isOne())
SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Disable);
else
SetHints(LoopHintAttr::UnrollCount, LoopHintAttr::Numeric);
} else
SetHints(LoopHintAttr::Unroll, LoopHintAttr::Enable);
} else if (PragmaName == "nounroll_and_jam") {
SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Disable);
Expand Down Expand Up @@ -142,7 +151,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
if (Option == LoopHintAttr::VectorizeWidth) {
assert((ValueExpr || (StateLoc && StateLoc->Ident)) &&
"Attribute must have a valid value expression or argument.");
if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc()))
if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc(),
/*AllowZero=*/false))
return nullptr;
if (StateLoc && StateLoc->Ident && StateLoc->Ident->isStr("scalable"))
State = LoopHintAttr::ScalableWidth;
Expand All @@ -152,7 +162,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
Option == LoopHintAttr::UnrollCount ||
Option == LoopHintAttr::PipelineInitiationInterval) {
assert(ValueExpr && "Attribute must have a valid value expression.");
if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc()))
if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc(),
/*AllowZero=*/false))
return nullptr;
State = LoopHintAttr::Numeric;
} else if (Option == LoopHintAttr::Vectorize ||
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2150,7 +2150,8 @@ TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
return LH;

// Generate error if there is a problem with the value.
if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation()))
if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation(),
LH->getOption() == LoopHintAttr::UnrollCount))
return LH;

// Create new LoopHintValueAttr with integral expression in place of the
Expand Down
18 changes: 9 additions & 9 deletions clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,23 @@ class CastValueChecker : public Checker<check::DeadSymbols, eval::Call> {

private:
// These are known in the LLVM project. The pairs are in the following form:
// {{{namespace, call}, argument-count}, {callback, kind}}
// {{match-mode, {namespace, call}, argument-count}, {callback, kind}}
const CallDescriptionMap<std::pair<CastCheck, CallKind>> CDM = {
{{{"llvm", "cast"}, 1},
{{CDM::SimpleFunc, {"llvm", "cast"}, 1},
{&CastValueChecker::evalCast, CallKind::Function}},
{{{"llvm", "dyn_cast"}, 1},
{{CDM::SimpleFunc, {"llvm", "dyn_cast"}, 1},
{&CastValueChecker::evalDynCast, CallKind::Function}},
{{{"llvm", "cast_or_null"}, 1},
{{CDM::SimpleFunc, {"llvm", "cast_or_null"}, 1},
{&CastValueChecker::evalCastOrNull, CallKind::Function}},
{{{"llvm", "dyn_cast_or_null"}, 1},
{{CDM::SimpleFunc, {"llvm", "dyn_cast_or_null"}, 1},
{&CastValueChecker::evalDynCastOrNull, CallKind::Function}},
{{{"clang", "castAs"}, 0},
{{CDM::CXXMethod, {"clang", "castAs"}, 0},
{&CastValueChecker::evalCastAs, CallKind::Method}},
{{{"clang", "getAs"}, 0},
{{CDM::CXXMethod, {"clang", "getAs"}, 0},
{&CastValueChecker::evalGetAs, CallKind::Method}},
{{{"llvm", "isa"}, 1},
{{CDM::SimpleFunc, {"llvm", "isa"}, 1},
{&CastValueChecker::evalIsa, CallKind::InstanceOf}},
{{{"llvm", "isa_and_nonnull"}, 1},
{{CDM::SimpleFunc, {"llvm", "isa_and_nonnull"}, 1},
{&CastValueChecker::evalIsaAndNonNull, CallKind::InstanceOf}}};

void evalCast(const CallEvent &Call, DefinedOrUnknownSVal DV,
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class ChrootChecker : public Checker<eval::Call, check::PreCall> {
// This bug refers to possibly break out of a chroot() jail.
const BugType BT_BreakJail{this, "Break out of jail"};

const CallDescription Chroot{{"chroot"}, 1}, Chdir{{"chdir"}, 1};
const CallDescription Chroot{CDM::CLibrary, {"chroot"}, 1},
Chdir{CDM::CLibrary, {"chdir"}, 1};

public:
ChrootChecker() {}
Expand Down
12 changes: 7 additions & 5 deletions clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,15 @@ class ErrnoTesterChecker : public Checker<eval::Call> {

using EvalFn = std::function<void(CheckerContext &, const CallEvent &)>;
const CallDescriptionMap<EvalFn> TestCalls{
{{{"ErrnoTesterChecker_setErrno"}, 1}, &ErrnoTesterChecker::evalSetErrno},
{{{"ErrnoTesterChecker_getErrno"}, 0}, &ErrnoTesterChecker::evalGetErrno},
{{{"ErrnoTesterChecker_setErrnoIfError"}, 0},
{{CDM::SimpleFunc, {"ErrnoTesterChecker_setErrno"}, 1},
&ErrnoTesterChecker::evalSetErrno},
{{CDM::SimpleFunc, {"ErrnoTesterChecker_getErrno"}, 0},
&ErrnoTesterChecker::evalGetErrno},
{{CDM::SimpleFunc, {"ErrnoTesterChecker_setErrnoIfError"}, 0},
&ErrnoTesterChecker::evalSetErrnoIfError},
{{{"ErrnoTesterChecker_setErrnoIfErrorRange"}, 0},
{{CDM::SimpleFunc, {"ErrnoTesterChecker_setErrnoIfErrorRange"}, 0},
&ErrnoTesterChecker::evalSetErrnoIfErrorRange},
{{{"ErrnoTesterChecker_setErrnoCheckState"}, 0},
{{CDM::SimpleFunc, {"ErrnoTesterChecker_setErrnoCheckState"}, 0},
&ErrnoTesterChecker::evalSetErrnoCheckState}};
};

Expand Down
5 changes: 2 additions & 3 deletions clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,15 @@ using namespace ento;

namespace {
class MmapWriteExecChecker : public Checker<check::PreCall> {
CallDescription MmapFn;
CallDescription MprotectFn;
CallDescription MmapFn{CDM::CLibrary, {"mmap"}, 6};
CallDescription MprotectFn{CDM::CLibrary, {"mprotect"}, 3};
static int ProtWrite;
static int ProtExec;
static int ProtRead;
const BugType BT{this, "W^X check fails, Write Exec prot flags set",
"Security"};

public:
MmapWriteExecChecker() : MmapFn({"mmap"}, 6), MprotectFn({"mprotect"}, 3) {}
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
int ProtExecOv;
int ProtReadOv;
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,11 @@ static llvm::StringRef indefiniteArticleBasedOnVowel(char a) {

class StdVariantChecker : public Checker<eval::Call, check::RegionChanges> {
// Call descriptors to find relevant calls
CallDescription VariantConstructor{{"std", "variant", "variant"}};
CallDescription VariantAssignmentOperator{{"std", "variant", "operator="}};
CallDescription StdGet{{"std", "get"}, 1, 1};
CallDescription VariantConstructor{CDM::CXXMethod,
{"std", "variant", "variant"}};
CallDescription VariantAssignmentOperator{CDM::CXXMethod,
{"std", "variant", "operator="}};
CallDescription StdGet{CDM::SimpleFunc, {"std", "get"}, 1, 1};

BugType BadVariantType{this, "BadVariantType", "BadVariantType"};

Expand Down Expand Up @@ -295,4 +297,4 @@ bool clang::ento::shouldRegisterStdVariantChecker(

void clang::ento::registerStdVariantChecker(clang::ento::CheckerManager &mgr) {
mgr.registerChecker<StdVariantChecker>();
}
}
2 changes: 1 addition & 1 deletion clang/lib/StaticAnalyzer/Checkers/StringChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class StringChecker : public Checker<check::PreCall> {
mutable const FunctionDecl *StringConstCharPtrCtor = nullptr;
mutable CanQualType SizeTypeTy;
const CallDescription TwoParamStdStringCtor = {
{"std", "basic_string", "basic_string"}, 2, 2};
CDM::CXXMethod, {"std", "basic_string", "basic_string"}, 2, 2};

bool isCharToStringCtor(const CallEvent &Call, const ASTContext &ACtx) const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class PutenvWithAutoChecker : public Checker<check::PostCall> {
private:
BugType BT{this, "'putenv' function should not be called with auto variables",
categories::SecurityError};
const CallDescription Putenv{{"putenv"}, 1};
const CallDescription Putenv{CDM::CLibrary, {"putenv"}, 1};

public:
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/StaticAnalyzer/Core/RegionStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2358,11 +2358,12 @@ StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {

RegionBindingsRef
RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
if (L.getAs<loc::ConcreteInt>())
// We only care about region locations.
auto MemRegVal = L.getAs<loc::MemRegionVal>();
if (!MemRegVal)
return B;

// If we get here, the location should be a region.
const MemRegion *R = L.castAs<loc::MemRegionVal>().getRegion();
const MemRegion *R = MemRegVal->getRegion();

// Check if the region is a struct region.
if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Analysis/gh-issue-89185.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s

void clang_analyzer_dump(char);
void clang_analyzer_dump_ptr(char*);

// https://github.com/llvm/llvm-project/issues/89185
void binding_to_label_loc() {
char *b = &&MyLabel;
MyLabel:
*b = 0; // no-crash
clang_analyzer_dump_ptr(b); // expected-warning {{&&MyLabel}}
clang_analyzer_dump(*b); // expected-warning {{Unknown}}
// FIXME: We should never reach here, as storing to a label is invalid.
}
3 changes: 3 additions & 0 deletions clang/test/CodeGen/debug-info-file-checksum.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// AIX does not support -gdwarf-5.
// UNSUPPORTED: target={{.*}}-aix{{.*}}

// RUN: %clang -emit-llvm -S -g -gcodeview -x c \
// RUN: %S/Inputs/debug-info-file-checksum.c -o - | FileCheck %s
// RUN: %clang -emit-llvm -S -g -gcodeview -Xclang -gsrc-hash=md5 \
Expand Down
7 changes: 5 additions & 2 deletions clang/test/CodeGen/dwarf-version.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@
// RUN: FileCheck %s --check-prefix=VER3
// RUN: %clang -target powerpc-ibm-aix-xcoff -gdwarf-4 -S -emit-llvm -o - %s | \
// RUN: FileCheck %s --check-prefix=VER4
// RUN: %clang -target powerpc-ibm-aix-xcoff -gdwarf-5 -S -emit-llvm -o - %s | \
// RUN: FileCheck %s --check-prefix=VER5
// RUN: not %clang -target powerpc-ibm-aix-xcoff -gdwarf-5 -S -emit-llvm -o - %s 2>&1 | \
// RUN: FileCheck %s --check-prefix=UNSUPPORTED-VER5
// RUN: not %clang -target powerpc64-ibm-aix-xcoff -gdwarf-5 -S -emit-llvm -o - %s 2>&1| \
// RUN: FileCheck %s --check-prefix=UNSUPPORTED-VER5

int main (void) {
return 0;
Expand All @@ -59,6 +61,7 @@ int main (void) {
// VER3: !{i32 7, !"Dwarf Version", i32 3}
// VER4: !{i32 7, !"Dwarf Version", i32 4}
// VER5: !{i32 7, !"Dwarf Version", i32 5}
// UNSUPPORTED-VER5: error: unsupported option '-gdwarf-5'

// NODWARF-NOT: !"Dwarf Version"
// CODEVIEW: !{i32 2, !"CodeView", i32 1}
Expand Down
33 changes: 31 additions & 2 deletions clang/test/CodeGen/ubsan-shift-bitint.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
// CHECK-LABEL: define{{.*}} i32 @test_left_variable
int test_left_variable(unsigned _BitInt(5) b, unsigned _BitInt(2) e) {
// CHECK: [[E_REG:%.+]] = load [[E_SIZE:i2]]
// CHECK: icmp ule [[E_SIZE]] [[E_REG]], -1
// CHECK: icmp ule [[E_SIZE]] [[E_REG]], -1,
return b << e;
}

// CHECK-LABEL: define{{.*}} i32 @test_right_variable
int test_right_variable(unsigned _BitInt(2) b, unsigned _BitInt(3) e) {
// CHECK: [[E_REG:%.+]] = load [[E_SIZE:i3]]
// CHECK: icmp ule [[E_SIZE]] [[E_REG]], 1
// CHECK: icmp ule [[E_SIZE]] [[E_REG]], 1,
return b >> e;
}

Expand All @@ -34,3 +34,32 @@ int test_right_literal(unsigned _BitInt(2) b) {
// CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds
return b >> 4uwb;
}

// CHECK-LABEL: define{{.*}} i32 @test_signed_left_variable
int test_signed_left_variable(unsigned _BitInt(15) b, _BitInt(2) e) {
// CHECK: [[E_REG:%.+]] = load [[E_SIZE:i2]]
// CHECK: icmp ule [[E_SIZE]] [[E_REG]], 1,
return b << e;
}

// CHECK-LABEL: define{{.*}} i32 @test_signed_right_variable
int test_signed_right_variable(unsigned _BitInt(32) b, _BitInt(4) e) {
// CHECK: [[E_REG:%.+]] = load [[E_SIZE:i4]]
// CHECK: icmp ule [[E_SIZE]] [[E_REG]], 7,
return b >> e;
}

// CHECK-LABEL: define{{.*}} i32 @test_signed_left_literal
int test_signed_left_literal(unsigned _BitInt(16) b) {
// CHECK-NOT: br i1 true, label %cont, label %handler.shift_out_of_bounds
// CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds
return b << (_BitInt(4))-2wb;
}

// CHECK-LABEL: define{{.*}} i32 @test_signed_right_literal
int test_signed_right_literal(unsigned _BitInt(16) b) {
// CHECK-NOT: br i1 true, label %cont, label %handler.shift_out_of_bounds
// CHECK: br i1 false, label %cont, label %handler.shift_out_of_bounds
return b >> (_BitInt(4))-8wb;
}

46 changes: 46 additions & 0 deletions clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -emit-llvm -mconstructor-aliases -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fclang-abi-compat=18 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=CLANG18 %s
// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=MSABI %s


class func {
public:
template <typename T>
func(T){};
template <typename T, typename U>
func(T, U){};
};

void GH88906(){
class Test{
public:
func a{[]{ }, []{ }};
func b{[]{ }};
func c{[]{ }};
} test;
}

// CHECK-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev
// CHECK: call void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_
// CHECK: call void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_
// CHECK: call void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_

// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_
// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_
// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_

// CLANG18-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev
// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EZ7GH88906vENS1_UlvE0_EEET_T0_
// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_
// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_



// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??0Test@?1??GH88906@@YAXXZ@QAE@XZ"
// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@a@Test@?1??GH88906@@YAXXZ@V<lambda_2>@12?1??3@YAXXZ@@func@@QAE@V<lambda_1>@a@Test@?1??GH88906@@YAXXZ@V<lambda_2>@23?1??4@YAXXZ@@Z"
// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@b@Test@?1??GH88906@@YAXXZ@@func@@QAE@V<lambda_1>@b@Test@?1??GH88906@@YAXXZ@@Z"
// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@c@Test@?1??GH88906@@YAXXZ@@func@@QAE@V<lambda_1>@c@Test@?1??GH88906@@YAXXZ@@Z"

// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@a@Test@?1??GH88906@@YAXXZ@V<lambda_2>@12?1??3@YAXXZ@@func@@QAE@V<lambda_1>@a@Test@?1??GH88906@@YAXXZ@V<lambda_2>@23?1??4@YAXXZ@@Z"
// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@b@Test@?1??GH88906@@YAXXZ@@func@@QAE@V<lambda_1>@b@Test@?1??GH88906@@YAXXZ@@Z"
// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@c@Test@?1??GH88906@@YAXXZ@@func@@QAE@V<lambda_1>@c@Test@?1??GH88906@@YAXXZ@@Z"
22 changes: 22 additions & 0 deletions clang/test/CodeGenCXX/pragma-gcc-unroll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,26 @@ void template_test(double *List, int Length) {
for_template_define_test<double>(List, Length, Value);
}

void for_unroll_zero_test(int *List, int Length) {
// CHECK: define {{.*}} @_Z20for_unroll_zero_testPii
#pragma GCC unroll 0
for (int i = 0; i < Length; i++) {
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_14:.*]]
List[i] = i * 2;
}
}

void while_unroll_zero_test(int *List, int Length) {
// CHECK: define {{.*}} @_Z22while_unroll_zero_testPii
int i = 0;
#pragma GCC unroll(0)
while (i < Length) {
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_15:.*]]
List[i] = i * 2;
i++;
}
}

// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], [[MP:![0-9]+]], ![[UNROLL_ENABLE:.*]]}
// CHECK: ![[UNROLL_ENABLE]] = !{!"llvm.loop.unroll.enable"}
// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]}
Expand All @@ -107,3 +127,5 @@ void template_test(double *List, int Length) {
// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_8:.*]]}
// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]]}
// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_8:.*]]}
// CHECK: ![[LOOP_14]] = distinct !{![[LOOP_14]], [[MP]], ![[UNROLL_DISABLE:.*]]}
// CHECK: ![[LOOP_15]] = distinct !{![[LOOP_15]], [[MP]], ![[UNROLL_DISABLE:.*]]}
28 changes: 14 additions & 14 deletions clang/test/Driver/aix-toolchain-include.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,28 @@
// RUN: --target=powerpc-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefixes=CHECK-INTERNAL-INCLUDE,CHECK-INTERNAL-INCLUDE-CXX %s

// RUN: %clangxx -### %s 2>&1 \
// RUN: --target=powerpc64-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefixes=CHECK-INTERNAL-INCLUDE,CHECK-INTERNAL-INCLUDE-CXX %s

// RUN: %clang -### -xc %s 2>&1 \
// RUN: --target=powerpc-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-INTERNAL-INCLUDE %s

// RUN: %clang -### -xc %s 2>&1 \
// RUN: --target=powerpc64-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-INTERNAL-INCLUDE %s

// CHECK-INTERNAL-INCLUDE: "-cc1"
Expand Down Expand Up @@ -78,31 +78,31 @@
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nostdlibinc \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-NOSTDLIBINC-INCLUDE %s

// RUN: %clangxx -### %s 2>&1 \
// RUN: --target=powerpc64-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nostdlibinc \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-NOSTDLIBINC-INCLUDE %s

// RUN: %clang -### -xc %s 2>&1 \
// RUN: --target=powerpc-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nostdlibinc \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-NOSTDLIBINC-INCLUDE %s

// RUN: %clang -### -xc %s 2>&1 \
// RUN: --target=powerpc64-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nostdlibinc \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-NOSTDLIBINC-INCLUDE %s

// CHECK-NOSTDLIBINC-INCLUDE: "-cc1"
Expand All @@ -120,31 +120,31 @@
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nobuiltininc \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefixes=CHECK-NOBUILTININC-INCLUDE,CHECK-NOBUILTININC-INCLUDE-CXX %s

// RUN: %clangxx -### %s 2>&1 \
// RUN: --target=powerpc64-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nobuiltininc \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefixes=CHECK-NOBUILTININC-INCLUDE,CHECK-NOBUILTININC-INCLUDE-CXX %s

// RUN: %clang -### -xc %s 2>&1 \
// RUN: --target=powerpc-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nobuiltininc \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-NOBUILTININC-INCLUDE %s

// RUN: %clang -### -xc %s 2>&1 \
// RUN: --target=powerpc64-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nobuiltininc \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-NOBUILTININC-INCLUDE %s

// CHECK-NOBUILTININC-INCLUDE: "-cc1"
Expand All @@ -162,15 +162,15 @@
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nostdinc++ \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-NOSTDINCXX-INCLUDE %s

// RUN: %clangxx -### %s 2>&1 \
// RUN: --target=powerpc64-ibm-aix \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_aix_tree \
// RUN: -nostdinc++ \
// RUN: -fopenmp \
// RUN: -fopenmp=libomp \
// RUN: | FileCheck -check-prefix=CHECK-NOSTDINCXX-INCLUDE %s

// CHECK-NOSTDINCXX-INCLUDE: "-cc1"
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Driver/cl-outputs.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@

// RUN: %clang_cl /Fefoo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXT %s
// RUN: %clang_cl /Fe:foo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXT %s
// RUN: %clang_cl /Fe: foo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXT %s
// FeEXT: "-out:foo.ext"

// RUN: %clang_cl /LD /Fefoo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXTDLL %s
Expand Down Expand Up @@ -270,6 +271,8 @@
// P: "-o" "cl-outputs.i"

// RUN: %clang_cl /P /Fifoo -### -- %s 2>&1 | FileCheck -check-prefix=Fi1 %s
// RUN: %clang_cl /P /Fi:foo -### -- %s 2>&1 | FileCheck -check-prefix=Fi1 %s
// RUN: %clang_cl /P /Fi: foo -### -- %s 2>&1 | FileCheck -check-prefix=Fi1 %s
// Fi1: "-E"
// Fi1: "-o" "foo.i"

Expand Down Expand Up @@ -302,6 +305,7 @@
// RELATIVE_OBJPATH1: "-object-file-name=a.obj"

// RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fo:a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH1_COLON %s
// RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fo: a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH1_COLON %s
// RELATIVE_OBJPATH1_COLON: "-object-file-name=a.obj"

// RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fofoo/a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH2 %s
Expand Down
6 changes: 6 additions & 0 deletions clang/test/Driver/cl-pch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@
// /Yu /Fpout.pch => out.pch is filename
// RUN: %clang_cl -Werror /Yupchfile.h /FIpchfile.h /Fpout.pch /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFP1 %s
// /Yu /Fp:out.pch => out.pch is filename
// RUN: %clang_cl -Werror /Yupchfile.h /FIpchfile.h /Fp:out.pch /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFP1 %s
// /Yu /Fp: out.pch => out.pch is filename
// RUN: %clang_cl -Werror /Yupchfile.h /FIpchfile.h /Fp: out.pch /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFP1 %s
// Use .pch file, but don't build it.
// CHECK-YUFP1: -include-pch
// CHECK-YUFP1: out.pch
Expand Down
19 changes: 11 additions & 8 deletions clang/test/Driver/clang-offload-bundler-zstd.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,22 @@
// Check compression/decompression of offload bundle.
//
// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \
// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose 2>&1 | \
// RUN: FileCheck -check-prefix=COMPRESS %s
// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose >%t.1.txt 2>&1
// RUN: clang-offload-bundler -type=bc -list -input=%t.hip.bundle.bc | FileCheck -check-prefix=NOHOST %s
// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \
// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle -verbose 2>&1 | \
// RUN: FileCheck -check-prefix=DECOMPRESS %s
// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle -verbose >%t.2.txt 2>&1
// RUN: cat %t.1.txt %t.2.txt | FileCheck %s
// RUN: diff %t.tgt1 %t.res.tgt1
// RUN: diff %t.tgt2 %t.res.tgt2
//
// COMPRESS: Compression method used: zstd
// COMPRESS: Compression level: 3
// DECOMPRESS: Decompression method: zstd
// DECOMPRESS: Hashes match: Yes
// CHECK: Compressed bundle format version: 2
// CHECK: Total file size (including headers): [[SIZE:[0-9]*]] bytes
// CHECK: Compression method used: zstd
// CHECK: Compression level: 3
// CHECK: Compressed bundle format version: 2
// CHECK: Total file size (from header): [[SIZE]] bytes
// CHECK: Decompression method: zstd
// CHECK: Hashes match: Yes
// NOHOST-NOT: host-
// NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900
// NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906
Expand Down
13 changes: 13 additions & 0 deletions clang/test/Driver/debug-options-embed-source.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// AIX does not support -gdwarf-5 which is required by -gembed-source
// UNSUPPORTED: target={{.*}}-aix{{.*}}

// RUN: %clang -### -gdwarf-5 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_5 %s
// RUN: not %clang -### -gdwarf-2 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_2 %s
// RUN: %clang -### -gdwarf-5 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_5 %s
// RUN: %clang -### -gdwarf-2 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_2 %s
//
// GEMBED_5: "-gembed-source"
// GEMBED_2: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'
// NOGEMBED_5-NOT: "-gembed-source"
// NOGEMBED_2-NOT: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'
//
10 changes: 0 additions & 10 deletions clang/test/Driver/debug-options.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,16 +410,6 @@
// MACRO: "-debug-info-macro"
// NOMACRO-NOT: "-debug-info-macro"
//
// RUN: %clang -### -gdwarf-5 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_5 %s
// RUN: not %clang -### -gdwarf-2 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_2 %s
// RUN: %clang -### -gdwarf-5 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_5 %s
// RUN: %clang -### -gdwarf-2 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_2 %s
//
// GEMBED_5: "-gembed-source"
// GEMBED_2: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'
// NOGEMBED_5-NOT: "-gembed-source"
// NOGEMBED_2-NOT: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'
//
// RUN: %clang -### -g -fno-eliminate-unused-debug-types -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=DEBUG_UNUSED_TYPES %s
// DEBUG_UNUSED_TYPES: "-debug-info-kind=unused-types"
Expand Down
6 changes: 6 additions & 0 deletions clang/test/Modules/pr85122.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// RUN: %clang_cc1 -std=c++20 %s -Wall -fsyntax-only -verify

// expected-no-diagnostics
export module a;

export constexpr auto a = []{};
8 changes: 6 additions & 2 deletions clang/test/Parser/pragma-unroll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,18 @@ void test(int *List, int Length) {

/* expected-error {{expected ')'}} */ #pragma unroll(()
/* expected-error {{expected expression}} */ #pragma unroll -
/* expected-error {{invalid value '0'; must be positive}} */ #pragma unroll(0)
/* expected-error {{invalid value '0'; must be positive}} */ #pragma unroll 0
/* The values of 0 and 1 block any unrolling of the loop. */ #pragma unroll 0
/* expected-error {{value '3000000000' is too large}} */ #pragma unroll(3000000000)
/* expected-error {{value '3000000000' is too large}} */ #pragma unroll 3000000000
while (i-8 < Length) {
List[i] = i;
}

/* The values of 0 and 1 block any unrolling of the loop. */ #pragma unroll(0)
while (i-8 < Length) {
List[i] = i;
}

#pragma unroll
/* expected-error {{expected a for, while, or do-while loop to follow '#pragma unroll'}} */ int j = Length;
#pragma unroll 4
Expand Down
6 changes: 5 additions & 1 deletion clang/test/Sema/aarch64-incompat-sm-builtin-calls.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -fsyntax-only -verify %s
// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -Waarch64-sme-attributes -fsyntax-only -verify %s

// REQUIRES: aarch64-registered-target

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

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

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

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

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

// Valid attributes

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

void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { }

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

void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible { }

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

void sme_no_streaming_with_vl_arg(__SVInt8_t a) { }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

void sme_streaming_compatible_calling_streaming_compatible_with_return_vl(void) __arm_streaming_compatible {
__SVInt8_t r = sme_streaming_compatible_returns_vl();
}
23 changes: 23 additions & 0 deletions clang/test/SemaCXX/aarch64-sve-resolve-type.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fsyntax-only %s

// REQUIRES: aarch64-registered-target || arm-registered-target

// expected-no-diagnostics

struct a {};
__SVFloat32_t b(a);
template <class c> using e = decltype(b(c()));
e<a> f(a);
template <class c> using h = decltype(f(c()));
template <class g> struct i {
static void j() {
a d;
g()(d);
}
};
struct k {
template <class c> void operator()(c) {
[](h<c>) {};
}
void l() { i<k>::j; }
};
81 changes: 0 additions & 81 deletions clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,56 +150,6 @@ TEST_F(EnvironmentTest, CreateValueRecursiveType) {
EXPECT_THAT(PV, NotNull());
}

TEST_F(EnvironmentTest, JoinRecords) {
using namespace ast_matchers;

std::string Code = R"cc(
struct S {};
// Need to use the type somewhere so that the `QualType` gets created;
S s;
)cc";

auto Unit =
tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"});
auto &Context = Unit->getASTContext();

ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U);

auto Results =
match(qualType(hasDeclaration(recordDecl(hasName("S")))).bind("SType"),
Context);
const QualType *TyPtr = selectFirst<QualType>("SType", Results);
ASSERT_THAT(TyPtr, NotNull());
QualType Ty = *TyPtr;
ASSERT_FALSE(Ty.isNull());

auto *ConstructExpr = CXXConstructExpr::CreateEmpty(Context, 0);
ConstructExpr->setType(Ty);
ConstructExpr->setValueKind(VK_PRValue);

// Two different `RecordValue`s with the same location are joined into a
// third `RecordValue` with that same location.
{
Environment Env1(DAContext);
auto &Val1 = *cast<RecordValue>(Env1.createValue(Ty));
RecordStorageLocation &Loc = Val1.getLoc();
Env1.setValue(Loc, Val1);

Environment Env2(DAContext);
auto &Val2 = Env2.create<RecordValue>(Loc);
Env2.setValue(Loc, Val2);
Env2.setValue(Loc, Val2);

Environment::ValueModel Model;
Environment EnvJoined =
Environment::join(Env1, Env2, Model, Environment::DiscardExprState);
auto *JoinedVal = cast<RecordValue>(EnvJoined.getValue(Loc));
EXPECT_NE(JoinedVal, &Val1);
EXPECT_NE(JoinedVal, &Val2);
EXPECT_EQ(&JoinedVal->getLoc(), &Loc);
}
}

TEST_F(EnvironmentTest, DifferentReferenceLocInJoin) {
// This tests the case where the storage location for a reference-type
// variable is different for two states being joined. We used to believe this
Expand Down Expand Up @@ -453,35 +403,4 @@ TEST_F(EnvironmentTest,
Contains(Member));
}

TEST_F(EnvironmentTest, RefreshRecordValue) {
using namespace ast_matchers;

std::string Code = R"cc(
struct S {};
void target () {
S s;
s;
}
)cc";

auto Unit =
tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"});
auto &Context = Unit->getASTContext();

ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U);

auto Results = match(functionDecl(hasName("target")).bind("target"), Context);
const auto *Target = selectFirst<FunctionDecl>("target", Results);
ASSERT_THAT(Target, NotNull());

Results = match(declRefExpr(to(varDecl(hasName("s")))).bind("s"), Context);
const auto *DRE = selectFirst<DeclRefExpr>("s", Results);
ASSERT_THAT(DRE, NotNull());

Environment Env(DAContext, *Target);
EXPECT_THAT(Env.getStorageLocation(*DRE), IsNull());
refreshRecordValue(*DRE, Env);
EXPECT_THAT(Env.getStorageLocation(*DRE), NotNull());
}

} // namespace
8 changes: 0 additions & 8 deletions clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,6 @@ TEST(RecordOpsTest, CopyRecord) {
EXPECT_NE(Env.getValue(S1.getSyntheticField("synth_int")),
Env.getValue(S2.getSyntheticField("synth_int")));

auto *S1Val = cast<RecordValue>(Env.getValue(S1));
auto *S2Val = cast<RecordValue>(Env.getValue(S2));
EXPECT_NE(S1Val, S2Val);

copyRecord(S1, S2, Env);

EXPECT_EQ(getFieldValue(&S1, *OuterIntDecl, Env),
Expand All @@ -98,10 +94,6 @@ TEST(RecordOpsTest, CopyRecord) {
getFieldValue(&Inner2, *InnerIntDecl, Env));
EXPECT_EQ(Env.getValue(S1.getSyntheticField("synth_int")),
Env.getValue(S2.getSyntheticField("synth_int")));

S1Val = cast<RecordValue>(Env.getValue(S1));
S2Val = cast<RecordValue>(Env.getValue(S2));
EXPECT_NE(S1Val, S2Val);
});
}

Expand Down
199 changes: 113 additions & 86 deletions clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,6 @@ TEST(TransferTest, StructIncomplete) {
ASSERT_THAT(FooValue, NotNull());

EXPECT_TRUE(isa<RecordStorageLocation>(FooValue->getPointeeLoc()));
auto *FooPointeeValue = Env.getValue(FooValue->getPointeeLoc());
ASSERT_THAT(FooPointeeValue, NotNull());
EXPECT_TRUE(isa<RecordValue>(FooPointeeValue));
});
}

Expand Down Expand Up @@ -311,9 +308,10 @@ TEST(TransferTest, StructFieldUnmodeled) {

const auto *FooLoc =
cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
const auto *UnmodeledLoc = FooLoc->getChild(*UnmodeledDecl);
ASSERT_TRUE(isa<RecordStorageLocation>(UnmodeledLoc));
EXPECT_THAT(Env.getValue(*UnmodeledLoc), IsNull());
const auto &UnmodeledLoc =
*cast<RecordStorageLocation>(FooLoc->getChild(*UnmodeledDecl));
StorageLocation &UnmodeledXLoc = getFieldLoc(UnmodeledLoc, "X", ASTCtx);
EXPECT_EQ(Env.getValue(UnmodeledXLoc), nullptr);

const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab");
ASSERT_THAT(ZabDecl, NotNull());
Expand Down Expand Up @@ -492,9 +490,6 @@ TEST(TransferTest, ReferenceVarDecl) {

const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));

const Value *FooReferentVal = Env.getValue(*FooLoc);
EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooReferentVal));
});
}

Expand Down Expand Up @@ -585,22 +580,21 @@ TEST(TransferTest, SelfReferentialReferenceVarDecl) {

const auto &FooReferentLoc =
*cast<RecordStorageLocation>(BarLoc.getChild(*FooRefDecl));
EXPECT_THAT(Env.getValue(FooReferentLoc), NotNull());
EXPECT_THAT(getFieldValue(&FooReferentLoc, *BarDecl, Env), IsNull());
EXPECT_EQ(Env.getValue(*cast<RecordStorageLocation>(
FooReferentLoc.getChild(*BarDecl))
->getChild(*FooPtrDecl)),
nullptr);

const auto &FooPtrVal =
*cast<PointerValue>(getFieldValue(&BarLoc, *FooPtrDecl, Env));
const auto &FooPtrPointeeLoc =
cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), NotNull());
EXPECT_THAT(getFieldValue(&FooPtrPointeeLoc, *BarDecl, Env), IsNull());

EXPECT_THAT(getFieldValue(&BarLoc, *BazRefDecl, Env), NotNull());
EXPECT_EQ(Env.getValue(*cast<RecordStorageLocation>(
FooPtrPointeeLoc.getChild(*BarDecl))
->getChild(*FooPtrDecl)),
nullptr);

const auto &BazPtrVal =
*cast<PointerValue>(getFieldValue(&BarLoc, *BazPtrDecl, Env));
const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc();
EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
EXPECT_TRUE(isa<PointerValue>(getFieldValue(&BarLoc, *BazPtrDecl, Env)));
});
}

Expand Down Expand Up @@ -631,9 +625,6 @@ TEST(TransferTest, PointerVarDecl) {
const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));

const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal));
});
}

Expand Down Expand Up @@ -740,20 +731,14 @@ TEST(TransferTest, SelfReferentialPointerVarDecl) {
const auto &BarPointeeLoc =
cast<RecordStorageLocation>(BarVal.getPointeeLoc());

EXPECT_THAT(getFieldValue(&BarPointeeLoc, *FooRefDecl, Env), NotNull());

const auto &FooPtrVal = *cast<PointerValue>(
getFieldValue(&BarPointeeLoc, *FooPtrDecl, Env));
const auto &FooPtrPointeeLoc =
cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());

EXPECT_THAT(getFieldValue(&BarPointeeLoc, *BazRefDecl, Env), NotNull());
EXPECT_EQ(Env.getValue(*FooPtrPointeeLoc.getChild(*BarDecl)), nullptr);

const auto &BazPtrVal = *cast<PointerValue>(
getFieldValue(&BarPointeeLoc, *BazPtrDecl, Env));
const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc();
EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
EXPECT_TRUE(
isa<PointerValue>(getFieldValue(&BarPointeeLoc, *BazPtrDecl, Env)));
});
}

Expand Down Expand Up @@ -1165,9 +1150,6 @@ TEST(TransferTest, ReferenceParamDecl) {

const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));

const Value *FooReferentVal = Env.getValue(*FooLoc);
EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooReferentVal));
});
}

Expand Down Expand Up @@ -1196,9 +1178,6 @@ TEST(TransferTest, PointerParamDecl) {
const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));

const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal));
});
}

Expand Down Expand Up @@ -1400,8 +1379,7 @@ static void derivedBaseMemberExpectations(

const auto &FooLoc =
*cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
const auto &FooVal = *cast<RecordValue>(Env.getValue(FooLoc));
EXPECT_EQ(&FooVal.getLoc(), &FooLoc);
EXPECT_NE(Env.getValue(*FooLoc.getChild(*BarDecl)), nullptr);
}

TEST(TransferTest, DerivedBaseMemberStructDefault) {
Expand Down Expand Up @@ -1850,7 +1828,6 @@ TEST(TransferTest, StructThisMember) {

const auto *QuxLoc =
cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());

const auto *BazVal =
cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
Expand Down Expand Up @@ -1921,7 +1898,6 @@ TEST(TransferTest, ClassThisMember) {

const auto *QuxLoc =
cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());

const auto *BazVal =
cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
Expand Down Expand Up @@ -2297,10 +2273,6 @@ TEST(TransferTest, AssignmentOperator) {
const auto *BarLoc2 =
cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));

const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
const auto *BarVal2 = cast<RecordValue>(Env2.getValue(*BarLoc2));
EXPECT_NE(FooVal2, BarVal2);

EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));

const auto *FooBazVal2 =
Expand Down Expand Up @@ -2652,12 +2624,7 @@ TEST(TransferTest, CopyConstructor) {
const auto *BarLoc =
cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));

// `Foo` and `Bar` have different `RecordValue`s associated with them.
const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc));
const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc));
EXPECT_NE(FooVal, BarVal);

// But the records compare equal.
// The records compare equal.
EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));

// In particular, the value of `Baz` in both records is the same.
Expand Down Expand Up @@ -2878,10 +2845,6 @@ TEST(TransferTest, MoveConstructor) {

EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));

const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1));
const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1));
EXPECT_NE(FooVal1, BarVal1);

const auto *FooBazVal1 =
cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
const auto *BarBazVal1 =
Expand All @@ -2890,8 +2853,6 @@ TEST(TransferTest, MoveConstructor) {

const auto *FooLoc2 =
cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
EXPECT_NE(FooVal2, BarVal1);
EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));

const auto *FooBazVal2 =
Expand Down Expand Up @@ -3098,6 +3059,79 @@ TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
});
}

TEST(TransferTest, ResultObjectLocationForInitListExpr) {
std::string Code = R"cc(
struct Inner {};

struct Outer { Inner I; };

void target() {
Outer O = { Inner() };
// [[p]]
}
)cc";
using ast_matchers::asString;
using ast_matchers::cxxConstructExpr;
using ast_matchers::hasType;
using ast_matchers::match;
using ast_matchers::selectFirst;
using ast_matchers::traverse;
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");

auto *Construct = selectFirst<CXXConstructExpr>(
"construct",
match(
cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
ASTCtx));

EXPECT_EQ(
&Env.getResultObjectLocation(*Construct),
&getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
"I", ASTCtx));
});
}

TEST(TransferTest, ResultObjectLocationForParenInitListExpr) {
std::string Code = R"cc(
struct Inner {};

struct Outer { Inner I; };

void target() {
Outer O((Inner()));
// [[p]]
}
)cc";
using ast_matchers::asString;
using ast_matchers::cxxConstructExpr;
using ast_matchers::hasType;
using ast_matchers::match;
using ast_matchers::selectFirst;
using ast_matchers::traverse;
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");

auto *Construct = selectFirst<CXXConstructExpr>(
"construct",
match(
cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
ASTCtx));

EXPECT_EQ(
&Env.getResultObjectLocation(*Construct),
&getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
"I", ASTCtx));
},
LangStandard::lang_cxx20);
}

// Check that the `std::strong_ordering` object returned by builtin `<=>` has a
// correctly modeled result object location.
TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
Expand Down Expand Up @@ -3443,7 +3477,8 @@ TEST(TransferTest, NullToPointerCast) {

const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
EXPECT_EQ(BazVal, &Env.fork().getOrCreateNullPointerValue(
BazPointeeLoc.getType()));

const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
Expand Down Expand Up @@ -3597,37 +3632,35 @@ TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {

TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
std::string Code = R"(
struct A {};
struct A {
int i;
};

void target(A Foo, A Bar, bool Cond) {
A Baz = Cond ? Foo : Bar;
// Make sure A::i is modeled.
Baz.i;
/*[[p]]*/
}
)";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");

const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
auto *FooIVal = cast<IntegerValue>(getFieldValue(
&getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo"), "i",
ASTCtx, Env));
auto *BarIVal = cast<IntegerValue>(getFieldValue(
&getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar"), "i",
ASTCtx, Env));
auto *BazIVal = cast<IntegerValue>(getFieldValue(
&getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Baz"), "i",
ASTCtx, Env));

const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());

const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
ASSERT_THAT(BazDecl, NotNull());

const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));

const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
ASSERT_THAT(BazVal, NotNull());

EXPECT_NE(BazVal, FooVal);
EXPECT_NE(BazVal, BarVal);
EXPECT_NE(BazIVal, FooIVal);
EXPECT_NE(BazIVal, BarIVal);
});
}

Expand Down Expand Up @@ -3894,7 +3927,6 @@ TEST(TransferTest, AssignToUnionMember) {
const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
Env.getStorageLocation(*BazDecl));
ASSERT_THAT(BazLoc, NotNull());
ASSERT_THAT(Env.getValue(*BazLoc), NotNull());

const auto *FooVal =
cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
Expand Down Expand Up @@ -5485,17 +5517,15 @@ TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
ASSERT_THAT(SDecl, NotNull());

auto *SLoc = Env.getStorageLocation(*SDecl);
ASSERT_THAT(SLoc, NotNull());
EXPECT_THAT(Env.getValue(*SLoc), NotNull());
EXPECT_THAT(SLoc, NotNull());

auto *Loc = Env.getReturnStorageLocation();
ASSERT_THAT(Loc, NotNull());
EXPECT_THAT(Env.getValue(*Loc), NotNull());
EXPECT_THAT(Loc, NotNull());

// TODO: We would really like to make this stronger assertion, but that
// doesn't work because we don't propagate values correctly through
// the conditional operator yet.
// ASSERT_THAT(Loc, Eq(SLoc));
// EXPECT_EQ(Loc, SLoc);
},
{BuiltinOptions{ContextSensitiveOptions{}}});
}
Expand Down Expand Up @@ -6561,7 +6591,7 @@ TEST(TransferTest, NewExpressions_Structs) {
void target() {
Outer *p = new Outer;
// Access the fields to make sure the analysis actually generates children
// for them in the `RecordStorageLocation` and `RecordValue`.
// for them in the `RecordStorageLocation`.
p->OuterField.InnerField;
// [[after_new]]
}
Expand All @@ -6583,9 +6613,6 @@ TEST(TransferTest, NewExpressions_Structs) {
*cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);

// Values for the struct and all fields exist after the new.
EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
});
}
Expand Down
6 changes: 6 additions & 0 deletions compiler-rt/cmake/Modules/CompilerRTUtils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,12 @@ macro(construct_compiler_rt_default_triple)
"Default triple for which compiler-rt runtimes will be built.")
endif()

if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
execute_process(COMMAND ${CMAKE_C_COMPILER} --target=${COMPILER_RT_DEFAULT_TARGET_TRIPLE} -print-target-triple
OUTPUT_VARIABLE COMPILER_RT_DEFAULT_TARGET_TRIPLE
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()

string(REPLACE "-" ";" LLVM_TARGET_TRIPLE_LIST ${COMPILER_RT_DEFAULT_TARGET_TRIPLE})
list(GET LLVM_TARGET_TRIPLE_LIST 0 COMPILER_RT_DEFAULT_TARGET_ARCH)

Expand Down
11 changes: 4 additions & 7 deletions flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void DataSharingProcessor::insertBarrier() {

void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
bool cmpCreated = false;
mlir::OpBuilder::InsertPoint localInsPt = firOpBuilder.saveInsertionPoint();
mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
for (const omp::Clause &clause : clauses) {
if (clause.id != llvm::omp::OMPC_lastprivate)
continue;
Expand Down Expand Up @@ -203,12 +203,11 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
// Lastprivate operation is inserted at the end
// of the lexically last section in the sections
// construct
mlir::OpBuilder::InsertPoint unstructuredSectionsIP =
firOpBuilder.saveInsertionPoint();
mlir::OpBuilder::InsertionGuard unstructuredSectionsGuard(
firOpBuilder);
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
firOpBuilder.setInsertionPoint(lastOper);
lastPrivIP = firOpBuilder.saveInsertionPoint();
firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP);
}
}
} else if (mlir::isa<mlir::omp::WsloopOp>(op)) {
Expand Down Expand Up @@ -268,7 +267,6 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
"simd/worksharing-loop");
}
}
firOpBuilder.restoreInsertionPoint(localInsPt);
}

void DataSharingProcessor::collectSymbols(
Expand Down Expand Up @@ -372,7 +370,7 @@ void DataSharingProcessor::doPrivatize(
uniquePrivatizerName))
return existingPrivatizer;

auto ip = firOpBuilder.saveInsertionPoint();
mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
firOpBuilder.setInsertionPoint(&moduleOp.getBodyRegion().front(),
moduleOp.getBodyRegion().front().begin());
auto result = firOpBuilder.create<mlir::omp::PrivateClauseOp>(
Expand Down Expand Up @@ -424,7 +422,6 @@ void DataSharingProcessor::doPrivatize(
}

symTable->popScope();
firOpBuilder.restoreInsertionPoint(ip);
return result;
}();

Expand Down
4 changes: 1 addition & 3 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter,
Fortran::lower::pft::Evaluation &eval) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
mlir::Location currentLocation = converter.getCurrentLocation();
mlir::OpBuilder::InsertPoint insPt = firOpBuilder.saveInsertionPoint();
mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock());

// If the symbol corresponds to the original ThreadprivateOp, use the symbol
Expand Down Expand Up @@ -197,8 +197,6 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter,
getExtendedValue(sexv, symThreadprivateValue);
converter.bindSymbol(*sym, symThreadprivateExv);
}

firOpBuilder.restoreInsertionPoint(insPt);
}

static mlir::Operation *
Expand Down
3 changes: 1 addition & 2 deletions flang/lib/Lower/OpenMP/ReductionProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,9 +486,8 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc,
assert(cstNeedsDealloc.has_value() &&
"createTempFromMold decides this statically");
if (cstNeedsDealloc.has_value() && *cstNeedsDealloc != false) {
auto insPt = builder.saveInsertionPoint();
mlir::OpBuilder::InsertionGuard guard(builder);
createReductionCleanupRegion(builder, loc, reductionDecl);
builder.restoreInsertionPoint(insPt);
}

// Put the temporary inside of a box:
Expand Down
10 changes: 10 additions & 0 deletions flang/lib/Semantics/check-cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
[&](const common::Indirection<parser::BackspaceStmt> &x) {
WarnOnIoStmt(source);
},
[&](const common::Indirection<parser::IfStmt> &x) {
Check(x.value());
},
[&](const auto &x) {
if (auto msg{ActionStmtChecker<IsCUFKernelDo>::WhyNotOk(x)}) {
context_.Say(source, std::move(*msg));
Expand All @@ -369,6 +372,13 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
Check(std::get<parser::Block>(eb->t));
}
}
void Check(const parser::IfStmt &is) {
const auto &uS{
std::get<parser::UnlabeledStatement<parser::ActionStmt>>(is.t)};
CheckUnwrappedExpr(
context_, uS.source, std::get<parser::ScalarLogicalExpr>(is.t));
Check(uS.statement, uS.source);
}
void Check(const parser::LoopControl::Bounds &bounds) {
Check(bounds.lower);
Check(bounds.upper);
Expand Down
5 changes: 3 additions & 2 deletions flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,9 +1042,10 @@ void CheckHelper::CheckObjectEntity(
parser::ToUpperCaseLetters(common::EnumToString(attr)));
}
} else if (!subpDetails && symbol.owner().kind() != Scope::Kind::Module &&
symbol.owner().kind() != Scope::Kind::MainProgram) {
symbol.owner().kind() != Scope::Kind::MainProgram &&
symbol.owner().kind() != Scope::Kind::BlockConstruct) {
messages_.Say(
"ATTRIBUTES(%s) may apply only to module, host subprogram, or device subprogram data"_err_en_US,
"ATTRIBUTES(%s) may apply only to module, host subprogram, block, or device subprogram data"_err_en_US,
parser::ToUpperCaseLetters(common::EnumToString(attr)));
}
}
Expand Down
11 changes: 11 additions & 0 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2286,6 +2286,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
CheckReductionTypeList(x);
}
}

bool OmpStructureChecker::CheckReductionOperators(
const parser::OmpClause::Reduction &x) {

Expand Down Expand Up @@ -2356,6 +2357,16 @@ void OmpStructureChecker::CheckReductionTypeList(
if (llvm::omp::nestedReduceWorkshareAllowedSet.test(GetContext().directive)) {
CheckSharedBindingInOuterContext(ompObjectList);
}

SymbolSourceMap symbols;
GetSymbolsInObjectList(ompObjectList, symbols);
for (auto &[symbol, source] : symbols) {
if (IsProcedurePointer(*symbol)) {
context_.Say(source,
"A procedure pointer '%s' must not appear in a REDUCTION clause."_err_en_US,
symbol->name());
}
}
}

void OmpStructureChecker::CheckIntentInPointerAndDefinable(
Expand Down
16 changes: 16 additions & 0 deletions flang/test/Semantics/OpenMP/reduction12.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp

! OpenMP 5.2: Section 5.5.5 : A procedure pointer must not appear in a
! reduction clause.

procedure(foo), pointer :: ptr
integer :: i
ptr => foo
!ERROR: A procedure pointer 'ptr' must not appear in a REDUCTION clause.
!$omp do reduction (+ : ptr)
do i = 1, 10
end do
contains
subroutine foo
end subroutine
end
5 changes: 5 additions & 0 deletions flang/test/Semantics/cuf03.cuf
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ module m
real, unified :: ru ! ok
type(t1), unified :: tu ! ok
type(t2) :: t ! ok

block
real, device :: a(100) ! ok
end block
end subroutine


end module
4 changes: 4 additions & 0 deletions flang/test/Semantics/cuf11.cuf
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ logical function compare_h(a,b)
!ERROR: 'b' is not an object of derived type; it is implicitly typed
compare_h = (a%h .eq. b%h)
end

attributes(global) subroutine sub2()
if (threadIdx%x == 1) print *, "I'm number one"
end subroutine
8 changes: 8 additions & 0 deletions flang/test/Semantics/cuf12.cuf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
! RUN: %python %S/test_errors.py %s %flang_fc1

program test
real, device :: b(100) ! ok
block
real, device :: a(100) ! ok
end block
end program
3 changes: 2 additions & 1 deletion libc/src/__support/FPUtil/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FENVIMPL_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FENVIMPL_H

#include "hdr/fenv_macros.h"
#include "hdr/math_macros.h"
#include "hdr/types/fenv_t.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/properties/architectures.h"
#include "src/errno/libc_errno.h"
#include <fenv.h>

#if defined(LIBC_TARGET_ARCH_IS_AARCH64)
#if defined(__APPLE__)
Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/FPUtil/riscv/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include "src/__support/macros/attributes.h" // For LIBC_INLINE_ASM
#include "src/__support/macros/config.h" // For LIBC_INLINE

#include <fenv.h>
#include <stdint.h>

namespace LIBC_NAMESPACE {
Expand Down
2 changes: 1 addition & 1 deletion libcxx/utils/ci/run-buildbot
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ function test-armv7m-picolibc() {
"${@}"

${NINJA} -vC "${BUILD_DIR}/compiler-rt" install
mv "${BUILD_DIR}/install/lib/armv7m-none-eabi"/* "${BUILD_DIR}/install/lib"
mv "${BUILD_DIR}/install/lib/armv7m-none-unknown-eabi"/* "${BUILD_DIR}/install/lib"

check-runtimes
}
Expand Down
4 changes: 4 additions & 0 deletions lld/docs/ld.lld.1
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ is specified, print to the map file.
Generate a merged
.Li .debug_names
section.
.It Fl -default-script Ns = Ns Ar file , Fl dT Ar file
In the absence of
.Fl -script ,
read this default linker script.
.It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression
Define a symbol alias.
.Ar expression
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/debug-names-bad.s
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# REQUIRES: x86
# REQUIRES: x86, system-linux
# RUN: rm -rf %t && mkdir %t && cd %t

## Test errors in the header.
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/default-script.s
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# RUN: ld.lld --default-script def.t b.t a.o -o out1
# RUN: llvm-readelf -Ss out1 | FileCheck %s --check-prefix=CHECK1
# RUN: ld.lld -dT def.t b.t a.o -o out1a && cmp out1 out1a
## The last -dT wins.
## If multiple -dT options are specified, the last -dT wins.
# RUN: ld.lld -dT a.t -dT def.t b.t a.o -o out1a && cmp out1 out1a

# RUN: mkdir d && cp def.t d/default.t
Expand Down
1 change: 0 additions & 1 deletion lldb/include/lldb/Core/Disassembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,6 @@ class Disassembler : public std::enable_shared_from_this<Disassembler>,
// Classes that inherit from Disassembler can see and modify these
ArchSpec m_arch;
InstructionList m_instruction_list;
lldb::addr_t m_base_addr;
std::string m_flavor;

private:
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/Symbol/CompilerType.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ class CompilerType {
bool omit_empty_base_classes,
std::vector<uint32_t> &child_indexes) const;

CompilerType GetDirectNestedTypeWithName(llvm::StringRef name) const;

/// Return the number of template arguments the type has.
/// If expand_pack is true, then variadic argument packs are automatically
/// expanded to their supplied arguments. If it is false an argument pack
Expand Down
7 changes: 7 additions & 0 deletions lldb/include/lldb/Symbol/TypeSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/lldb-private.h"
#include "lldb/lldb-types.h"

class PDBASTParser;

Expand Down Expand Up @@ -363,6 +364,12 @@ class TypeSystem : public PluginInterface,
lldb::opaque_compiler_type_t type, llvm::StringRef name,
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) = 0;

virtual CompilerType
GetDirectNestedTypeWithName(lldb::opaque_compiler_type_t type,
llvm::StringRef name) {
return CompilerType();
}

virtual bool IsTemplateType(lldb::opaque_compiler_type_t type);

virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
Expand Down
3 changes: 1 addition & 2 deletions lldb/source/Core/Disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1117,8 +1117,7 @@ size_t Disassembler::ParseInstructions(Target &target, Address start,

// Disassembler copy constructor
Disassembler::Disassembler(const ArchSpec &arch, const char *flavor)
: m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS),
m_flavor() {
: m_arch(arch), m_instruction_list(), m_flavor() {
if (flavor == nullptr)
m_flavor.assign("default");
else
Expand Down
Loading