137 changes: 55 additions & 82 deletions clang/lib/APINotes/APINotesReader.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4534,7 +4534,7 @@ unsigned FunctionDecl::getODRHash() {
}

class ODRHash Hash;
Hash.AddFunctionDecl(this, /*SkipBody=*/shouldSkipCheckingODR());
Hash.AddFunctionDecl(this);
setHasODRHash(true);
ODRHash = Hash.CalculateHash();
return ODRHash;
Expand Down
5 changes: 0 additions & 5 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1106,11 +1106,6 @@ bool Decl::isFromExplicitGlobalModule() const {
return getOwningModule() && getOwningModule()->isExplicitGlobalModule();
}

bool Decl::shouldSkipCheckingODR() const {
return getASTContext().getLangOpts().SkipODRCheckInGMF &&
isFromExplicitGlobalModule();
}

static Decl::Kind getKind(const Decl *D) { return D->getKind(); }
static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); }

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->discard(SubExpr);

std::optional<PrimType> FromT = classify(SubExpr->getType());
std::optional<PrimType> ToT = classifyPrim(CE->getType());
std::optional<PrimType> ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;

Expand Down
22 changes: 20 additions & 2 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2071,13 +2071,31 @@ StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
}

CXXRecordDecl *Lambda = S->getLambdaClass();
ID.AddInteger(Lambda->getODRHash());

for (const auto &Capture : Lambda->captures()) {
ID.AddInteger(Capture.getCaptureKind());
if (Capture.capturesVariable())
VisitDecl(Capture.getCapturedVar());
}

// Profiling the body of the lambda may be dangerous during deserialization.
// So we'd like only to profile the signature here.
ODRHash Hasher;
// FIXME: We can't get the operator call easily by
// `CXXRecordDecl::getLambdaCallOperator()` if we're in deserialization.
// So we have to do something raw here.
for (auto *SubDecl : Lambda->decls()) {
FunctionDecl *Call = nullptr;
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(SubDecl))
Call = FTD->getTemplatedDecl();
else if (auto *FD = dyn_cast<FunctionDecl>(SubDecl))
Call = FD;

if (!Call)
continue;

Hasher.AddFunctionDecl(Call, /*SkipBody=*/true);
}
ID.AddInteger(Hasher.CalculateHash());
}

void
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,11 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> {
isa<CXXStdInitializerListExpr>(E)) {
return;
}
if (auto *Op = dyn_cast<BinaryOperator>(E);
Op && Op->getOpcode() == BO_Cmp) {
// Builtin `<=>` returns a `std::strong_ordering` object.
return;
}

if (auto *InitList = dyn_cast<InitListExpr>(E)) {
if (!InitList->isSemanticForm())
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18194,7 +18194,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
/*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
Intrinsic::dx_any, ArrayRef<Value *>{Op0}, nullptr, "dx.any");
CGM.getHLSLRuntime().getAnyIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
"hlsl.any");
}
case Builtin::BI__builtin_hlsl_elementwise_clamp: {
Value *OpX = EmitScalarExpr(E->getArg(0));
Expand Down
13 changes: 7 additions & 6 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4694,11 +4694,11 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
AggValueSlot Slot = args.isUsingInAlloca()
? createPlaceholderSlot(*this, type) : CreateAggTemp(type, "agg.tmp");

bool DestroyedInCallee = true, NeedsEHCleanup = true;
bool DestroyedInCallee = true, NeedsCleanup = true;
if (const auto *RD = type->getAsCXXRecordDecl())
DestroyedInCallee = RD->hasNonTrivialDestructor();
else
NeedsEHCleanup = needsEHCleanup(type.isDestructedType());
NeedsCleanup = type.isDestructedType();

if (DestroyedInCallee)
Slot.setExternallyDestructed();
Expand All @@ -4707,14 +4707,15 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
RValue RV = Slot.asRValue();
args.add(RV, type);

if (DestroyedInCallee && NeedsEHCleanup) {
if (DestroyedInCallee && NeedsCleanup) {
// Create a no-op GEP between the placeholder and the cleanup so we can
// RAUW it successfully. It also serves as a marker of the first
// instruction where the cleanup is active.
pushFullExprCleanup<DestroyUnpassedArg>(EHCleanup, Slot.getAddress(),
type);
pushFullExprCleanup<DestroyUnpassedArg>(NormalAndEHCleanup,
Slot.getAddress(), type);
// This unreachable is a temporary marker which will be removed later.
llvm::Instruction *IsActive = Builder.CreateUnreachable();
llvm::Instruction *IsActive =
Builder.CreateFlagLoad(llvm::Constant::getNullValue(Int8PtrTy));
args.addArgCleanupDeactivation(EHStack.stable_begin(), IsActive);
}
return;
Expand Down
37 changes: 23 additions & 14 deletions clang/lib/CodeGen/CGCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -634,12 +634,19 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF,
/// Pops a cleanup block. If the block includes a normal cleanup, the
/// current insertion point is threaded through the cleanup, as are
/// any branch fixups on the cleanup.
void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
bool ForDeactivation) {
assert(!EHStack.empty() && "cleanup stack is empty!");
assert(isa<EHCleanupScope>(*EHStack.begin()) && "top not a cleanup!");
EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin());
assert(Scope.getFixupDepth() <= EHStack.getNumBranchFixups());

// If we are deactivating a normal cleanup, we need to pretend that the
// fallthrough is unreachable. We restore this IP before returning.
CGBuilderTy::InsertPoint NormalDeactivateOrigIP;
if (ForDeactivation && (Scope.isNormalCleanup() || !getLangOpts().EHAsynch)) {
NormalDeactivateOrigIP = Builder.saveAndClearIP();
}
// Remember activation information.
bool IsActive = Scope.isActive();
Address NormalActiveFlag =
Expand Down Expand Up @@ -729,6 +736,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
EHStack.popCleanup(); // safe because there are no fixups
assert(EHStack.getNumBranchFixups() == 0 ||
EHStack.hasNormalCleanups());
if (NormalDeactivateOrigIP.isSet())
Builder.restoreIP(NormalDeactivateOrigIP);
return;
}

Expand Down Expand Up @@ -765,9 +774,16 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
if (!RequiresNormalCleanup) {
// Mark CPP scope end for passed-by-value Arg temp
// per Windows ABI which is "normally" Cleanup in callee
if (IsEHa && getInvokeDest() && Builder.GetInsertBlock()) {
if (Personality.isMSVCXXPersonality())
if (IsEHa && getInvokeDest()) {
// If we are deactivating a normal cleanup then we don't have a
// fallthrough. Restore original IP to emit CPP scope ends in the correct
// block.
if (NormalDeactivateOrigIP.isSet())
Builder.restoreIP(NormalDeactivateOrigIP);
if (Personality.isMSVCXXPersonality() && Builder.GetInsertBlock())
EmitSehCppScopeEnd();
if (NormalDeactivateOrigIP.isSet())
NormalDeactivateOrigIP = Builder.saveAndClearIP();
}
destroyOptimisticNormalEntry(*this, Scope);
Scope.MarkEmitted();
Expand Down Expand Up @@ -992,6 +1008,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
}
}

if (NormalDeactivateOrigIP.isSet())
Builder.restoreIP(NormalDeactivateOrigIP);
assert(EHStack.hasNormalCleanups() || EHStack.getNumBranchFixups() == 0);

// Emit the EH cleanup if required.
Expand Down Expand Up @@ -1281,17 +1299,8 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C,
// to the current RunCleanupsScope.
if (C == EHStack.stable_begin() &&
CurrentCleanupScopeDepth.strictlyEncloses(C)) {
// Per comment below, checking EHAsynch is not really necessary
// it's there to assure zero-impact w/o EHAsynch option
if (!Scope.isNormalCleanup() && getLangOpts().EHAsynch) {
PopCleanupBlock();
} else {
// If it's a normal cleanup, we need to pretend that the
// fallthrough is unreachable.
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
PopCleanupBlock();
Builder.restoreIP(SavedIP);
}
PopCleanupBlock(/*FallthroughIsBranchThrough=*/false,
/*ForDeactivation=*/true);
return;
}

Expand Down
7 changes: 5 additions & 2 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2216,8 +2216,11 @@ void CodeGenFunction::pushDestroyAndDeferDeactivation(
void CodeGenFunction::pushDestroyAndDeferDeactivation(
CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray) {
pushCleanupAndDeferDeactivation<DestroyObject>(
cleanupKind, addr, type, destroyer, useEHCleanupForArray);
llvm::Instruction *DominatingIP =
Builder.CreateFlagLoad(llvm::Constant::getNullValue(Int8PtrTy));
pushDestroy(cleanupKind, addr, type, destroyer, useEHCleanupForArray);
DeferredDeactivationCleanupStack.push_back(
{EHStack.stable_begin(), DominatingIP});
}

void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class CGHLSLRuntime {
//===----------------------------------------------------------------------===//

GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)

//===----------------------------------------------------------------------===//
Expand Down
84 changes: 44 additions & 40 deletions clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ namespace {
/// contains enough information to determine where the runs break. Microsoft
/// and Itanium follow different rules and use different codepaths.
/// * It is desired that, when possible, bitfields use the appropriate iN type
/// when lowered to llvm types. For example unsigned x : 24 gets lowered to
/// when lowered to llvm types. For example unsigned x : 24 gets lowered to
/// i24. This isn't always possible because i24 has storage size of 32 bit
/// and if it is possible to use that extra byte of padding we must use
/// [i8 x 3] instead of i24. The function clipTailPadding does this.
/// and if it is possible to use that extra byte of padding we must use [i8 x
/// 3] instead of i24. This is computed when accumulating bitfields in
/// accumulateBitfields.
/// C++ examples that require clipping:
/// struct { int a : 24; char b; }; // a must be clipped, b goes at offset 3
/// struct A { int a : 24; ~A(); }; // a must be clipped because:
Expand All @@ -62,11 +63,7 @@ namespace {
/// that the tail padding is not used in the complete class.) However,
/// because LLVM reads from the complete type it can generate incorrect code
/// if we do not clip the tail padding off of the bitfield in the complete
/// layout. This introduces a somewhat awkward extra unnecessary clip stage.
/// The location of the clip is stored internally as a sentinel of type
/// SCISSOR. If LLVM were updated to read base types (which it probably
/// should because locations of things such as VBases are bogus in the llvm
/// type anyway) then we could eliminate the SCISSOR.
/// layout.
/// * Itanium allows nearly empty primary virtual bases. These bases don't get
/// get their own storage because they're laid out as part of another base
/// or at the beginning of the structure. Determining if a VBase actually
Expand Down Expand Up @@ -200,9 +197,7 @@ struct CGRecordLowering {
const CXXRecordDecl *Query) const;
void calculateZeroInit();
CharUnits calculateTailClippingOffset(bool isNonVirtualBaseType) const;
/// Lowers bitfield storage types to I8 arrays for bitfields with tail
/// padding that is or can potentially be used.
void clipTailPadding();
void checkBitfieldClipping() const;
/// Determines if we need a packed llvm struct.
void determinePacked(bool NVBaseType);
/// Inserts padding everywhere it's needed.
Expand Down Expand Up @@ -305,7 +300,7 @@ void CGRecordLowering::lower(bool NVBaseType) {
}
llvm::stable_sort(Members);
Members.push_back(StorageInfo(Size, getIntNType(8)));
clipTailPadding();
checkBitfieldClipping();
determinePacked(NVBaseType);
insertPadding();
Members.pop_back();
Expand Down Expand Up @@ -531,6 +526,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
// available padding characters.
RecordDecl::field_iterator BestEnd = Begin;
CharUnits BestEndOffset;
bool BestClipped; // Whether the representation must be in a byte array.

for (;;) {
// AtAlignedBoundary is true iff Field is the (potential) start of a new
Expand Down Expand Up @@ -593,10 +589,9 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
// this is the best seen so far.
BestEnd = Field;
BestEndOffset = BeginOffset + AccessSize;
if (Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
// Fine-grained access, so no merging of spans.
InstallBest = true;
else if (!BitSizeSinceBegin)
// Assume clipped until proven not below.
BestClipped = true;
if (!BitSizeSinceBegin)
// A zero-sized initial span -- this will install nothing and reset
// for another.
InstallBest = true;
Expand Down Expand Up @@ -624,6 +619,12 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
// The access unit is not at a naturally aligned offset within the
// structure.
InstallBest = true;

if (InstallBest && BestEnd == Field)
// We're installing the first span, whose clipping was presumed
// above. Compute it correctly.
if (getSize(Type) == AccessSize)
BestClipped = false;
}

if (!InstallBest) {
Expand Down Expand Up @@ -656,11 +657,15 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
// access unit.
BestEndOffset = BeginOffset + TypeSize;
BestEnd = Field;
BestClipped = false;
}

if (Barrier)
// The next field is a barrier that we cannot merge across.
InstallBest = true;
else if (Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
// Fine-grained access, so no merging of spans.
InstallBest = true;
else
// Otherwise, we're not installing. Update the bit size
// of the current span to go all the way to LimitOffset, which is
Expand All @@ -679,7 +684,17 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
// Add the storage member for the access unit to the record. The
// bitfields get the offset of their storage but come afterward and
// remain there after a stable sort.
llvm::Type *Type = getIntNType(Context.toBits(AccessSize));
llvm::Type *Type;
if (BestClipped) {
assert(getSize(getIntNType(Context.toBits(AccessSize))) >
AccessSize &&
"Clipped access need not be clipped");
Type = getByteArrayType(AccessSize);
} else {
Type = getIntNType(Context.toBits(AccessSize));
assert(getSize(Type) == AccessSize &&
"Unclipped access must be clipped");
}
Members.push_back(StorageInfo(BeginOffset, Type));
for (; Begin != BestEnd; ++Begin)
if (!Begin->isZeroLengthBitField(Context))
Expand Down Expand Up @@ -934,32 +949,21 @@ void CGRecordLowering::calculateZeroInit() {
}
}

void CGRecordLowering::clipTailPadding() {
std::vector<MemberInfo>::iterator Prior = Members.begin();
CharUnits Tail = getSize(Prior->Data);
for (std::vector<MemberInfo>::iterator Member = Prior + 1,
MemberEnd = Members.end();
Member != MemberEnd; ++Member) {
// Verify accumulateBitfields computed the correct storage representations.
void CGRecordLowering::checkBitfieldClipping() const {
#ifndef NDEBUG
auto Tail = CharUnits::Zero();
for (const auto &M : Members) {
// Only members with data and the scissor can cut into tail padding.
if (!Member->Data && Member->Kind != MemberInfo::Scissor)
if (!M.Data && M.Kind != MemberInfo::Scissor)
continue;
if (Member->Offset < Tail) {
assert(Prior->Kind == MemberInfo::Field &&
"Only storage fields have tail padding!");
if (!Prior->FD || Prior->FD->isBitField())
Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8)));
else {
assert(Prior->FD->hasAttr<NoUniqueAddressAttr>() &&
"should not have reused this field's tail padding");
Prior->Data = getByteArrayType(
Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).Width);
}
}
if (Member->Data)
Prior = Member;
Tail = Prior->Offset + getSize(Prior->Data);

assert(M.Offset >= Tail && "Bitfield access unit is not clipped");
Tail = M.Offset;
if (M.Data)
Tail += getSize(M.Data);
}
#endif
}

void CGRecordLowering::determinePacked(bool NVBaseType) {
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,8 @@ class CodeGenFunction : public CodeGenTypeCache {

/// PopCleanupBlock - Will pop the cleanup entry on the stack and
/// process all branch fixups.
void PopCleanupBlock(bool FallThroughIsBranchThrough = false);
void PopCleanupBlock(bool FallThroughIsBranchThrough = false,
bool ForDeactivation = false);

/// DeactivateCleanupBlock - Deactivates the given cleanup block.
/// The block cannot be reactivated. Pops it if it's the top of the
Expand Down
17 changes: 14 additions & 3 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3952,9 +3952,20 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
// behavior may break ABI compatibility of the current unit.
if (const Module *M = F->getOwningModule();
M && M->getTopLevelModule()->isNamedModule() &&
getContext().getCurrentNamedModule() != M->getTopLevelModule() &&
!F->hasAttr<AlwaysInlineAttr>())
return false;
getContext().getCurrentNamedModule() != M->getTopLevelModule()) {
// There are practices to mark template member function as always-inline
// and mark the template as extern explicit instantiation but not give
// the definition for member function. So we have to emit the function
// from explicitly instantiation with always-inline.
//
// See https://github.com/llvm/llvm-project/issues/86893 for details.
//
// TODO: Maybe it is better to give it a warning if we call a non-inline
// function from other module units which is marked as always-inline.
if (!F->isTemplateInstantiation() || !F->hasAttr<AlwaysInlineAttr>()) {
return false;
}
}

if (F->hasAttr<NoInlineAttr>())
return false;
Expand Down
4 changes: 0 additions & 4 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2380,10 +2380,6 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
if (getLangOpts().CPlusPlus23) {
auto &LastRecord = Actions.ExprEvalContexts.back();
LastRecord.InLifetimeExtendingContext = true;

// Materialize non-`cv void` prvalue temporaries in discarded
// expressions. These materialized temporaries may be lifetime-extented.
LastRecord.InMaterializeTemporaryObjectContext = true;
}

if (getLangOpts().OpenMP)
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set(LLVM_LINK_COMPONENTS
Core
Demangle
FrontendHLSL
FrontendOpenMP
MC
Expand Down
44 changes: 33 additions & 11 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/IR/Assumptions.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/Support/Error.h"
Expand Down Expand Up @@ -1983,6 +1984,36 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context) WeakRefAttr(S.Context, AL));
}

// Mark alias/ifunc target as used. Due to name mangling, we look up the
// demangled name ignoring parameters (not supported by microsoftDemangle
// https://github.com/llvm/llvm-project/issues/88825). This should handle the
// majority of use cases while leaving namespace scope names unmarked.
static void markUsedForAliasOrIfunc(Sema &S, Decl *D, const ParsedAttr &AL,
StringRef Str) {
std::unique_ptr<char, llvm::FreeDeleter> Demangled;
if (S.getASTContext().getCXXABIKind() != TargetCXXABI::Microsoft)
Demangled.reset(llvm::itaniumDemangle(Str, /*ParseParams=*/false));
std::unique_ptr<MangleContext> MC(S.Context.createMangleContext());
SmallString<256> Name;

const DeclarationNameInfo Target(
&S.Context.Idents.get(Demangled ? Demangled.get() : Str), AL.getLoc());
LookupResult LR(S, Target, Sema::LookupOrdinaryName);
if (S.LookupName(LR, S.TUScope)) {
for (NamedDecl *ND : LR) {
if (MC->shouldMangleDeclName(ND)) {
llvm::raw_svector_ostream Out(Name);
Name.clear();
MC->mangleName(GlobalDecl(ND), Out);
} else {
Name = ND->getIdentifier()->getName();
}
if (Name == Str)
ND->markUsed(S.Context);
}
}
}

static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
Expand All @@ -1995,6 +2026,7 @@ static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
return;
}

markUsedForAliasOrIfunc(S, D, AL, Str);
D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str));
}

Expand Down Expand Up @@ -2029,17 +2061,7 @@ static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
}

// Mark target used to prevent unneeded-internal-declaration warnings.
if (!S.LangOpts.CPlusPlus) {
// FIXME: demangle Str for C++, as the attribute refers to the mangled
// linkage name, not the pre-mangled identifier.
const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc());
LookupResult LR(S, target, Sema::LookupOrdinaryName);
if (S.LookupQualifiedName(LR, S.getCurLexicalContext()))
for (NamedDecl *ND : LR)
ND->markUsed(S.Context);
}

markUsedForAliasOrIfunc(S, D, AL, Str);
D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str));
}

Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6314,7 +6314,6 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
// Pass down lifetime extending flag, and collect temporaries in
// CreateMaterializeTemporaryExpr when we rewrite the call argument.
keepInLifetimeExtendingContext();
keepInMaterializeTemporaryObjectContext();
EnsureImmediateInvocationInDefaultArgs Immediate(*this);
ExprResult Res;
runWithSufficientStackSpace(CallLoc, [&] {
Expand Down Expand Up @@ -7740,7 +7739,8 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
}

if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
if (Method->isImplicitObjectMemberFunction())
if (!isa<RequiresExprBodyDecl>(CurContext) &&
Method->isImplicitObjectMemberFunction())
return ExprError(Diag(LParenLoc, diag::err_member_call_without_object)
<< Fn->getSourceRange() << 0);

Expand Down Expand Up @@ -18679,9 +18679,9 @@ void Sema::PopExpressionEvaluationContext() {
// Append the collected materialized temporaries into previous context before
// exit if the previous also is a lifetime extending context.
auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
if (getLangOpts().CPlusPlus23 && isInLifetimeExtendingContext() &&
PrevRecord.InLifetimeExtendingContext && !ExprEvalContexts.empty()) {
auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext &&
PrevRecord.InLifetimeExtendingContext &&
!Rec.ForRangeLifetimeExtendTemps.empty()) {
PrevRecord.ForRangeLifetimeExtendTemps.append(
Rec.ForRangeLifetimeExtendTemps);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8429,7 +8429,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
// unnecessary temporary objects. If we skip this step, IR generation is
// able to synthesize the storage for itself in the aggregate case, and
// adding the extra node to the AST is just clutter.
if (isInMaterializeTemporaryObjectContext() && getLangOpts().CPlusPlus17 &&
if (isInLifetimeExtendingContext() && getLangOpts().CPlusPlus17 &&
E->isPRValue() && !E->getType()->isVoidType()) {
ExprResult Res = TemporaryMaterializationConversion(E);
if (Res.isInvalid())
Expand Down
13 changes: 10 additions & 3 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14395,9 +14395,16 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
ArrayRef<Expr *> ArgsArray(Args, NumArgs);

if (Input->isTypeDependent()) {
ExprValueKind VK = ExprValueKind::VK_PRValue;
// [C++26][expr.unary.op][expr.pre.incr]
// The * operator yields an lvalue of type
// The pre/post increment operators yied an lvalue.
if (Opc == UO_PreDec || Opc == UO_PreInc || Opc == UO_Deref)
VK = VK_LValue;

if (Fns.empty())
return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
VK_PRValue, OK_Ordinary, OpLoc, false,
return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy, VK,
OK_Ordinary, OpLoc, false,
CurFPFeatureOverrides());

CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
Expand All @@ -14406,7 +14413,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray,
Context.DependentTy, VK_PRValue, OpLoc,
Context.DependentTy, VK, OpLoc,
CurFPFeatureOverrides());
}

Expand Down
1 change: 0 additions & 1 deletion clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5483,7 +5483,6 @@ void Sema::InstantiateVariableInitializer(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var);

keepInLifetimeExtendingContext();
keepInMaterializeTemporaryObjectContext();
// Instantiate the initializer.
ExprResult Init;

Expand Down
5 changes: 0 additions & 5 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -4177,7 +4177,6 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
getSema(), EnterExpressionEvaluationContext::InitList,
Construct->isListInitialization());

getSema().keepInLifetimeExtendingContext();
getSema().keepInLifetimeExtendingContext();
SmallVector<Expr*, 8> NewArgs;
bool ArgChanged = false;
Expand Down Expand Up @@ -8752,10 +8751,6 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
if (getSema().getLangOpts().CPlusPlus23) {
auto &LastRecord = getSema().ExprEvalContexts.back();
LastRecord.InLifetimeExtendingContext = true;

// Materialize non-`cv void` prvalue temporaries in discarded
// expressions. These materialized temporaries may be lifetime-extented.
LastRecord.InMaterializeTemporaryObjectContext = true;
}
StmtResult Init =
S->getInit() ? getDerived().TransformStmt(S->getInit()) : StmtResult();
Expand Down
89 changes: 38 additions & 51 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -915,10 +915,9 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
using namespace llvm::support;

SelectorTable &SelTable = Reader.getContext().Selectors;
unsigned N =
endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
unsigned N = endian::readNext<uint16_t, llvm::endianness::little>(d);
const IdentifierInfo *FirstII = Reader.getLocalIdentifier(
F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d));
F, endian::readNext<uint32_t, llvm::endianness::little>(d));
if (N == 0)
return SelTable.getNullarySelector(FirstII);
else if (N == 1)
Expand All @@ -928,7 +927,7 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
Args.push_back(FirstII);
for (unsigned I = 1; I != N; ++I)
Args.push_back(Reader.getLocalIdentifier(
F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)));
F, endian::readNext<uint32_t, llvm::endianness::little>(d)));

return SelTable.getSelector(N, Args.data());
}
Expand All @@ -941,11 +940,11 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
data_type Result;

Result.ID = Reader.getGlobalSelectorID(
F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d));
F, endian::readNext<uint32_t, llvm::endianness::little>(d));
unsigned FullInstanceBits =
endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
endian::readNext<uint16_t, llvm::endianness::little>(d);
unsigned FullFactoryBits =
endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
endian::readNext<uint16_t, llvm::endianness::little>(d);
Result.InstanceBits = FullInstanceBits & 0x3;
Result.InstanceHasMoreThanOneDecl = (FullInstanceBits >> 2) & 0x1;
Result.FactoryBits = FullFactoryBits & 0x3;
Expand All @@ -956,16 +955,14 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
// Load instance methods
for (unsigned I = 0; I != NumInstanceMethods; ++I) {
if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>(
F,
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)))
F, endian::readNext<uint32_t, llvm::endianness::little>(d)))
Result.Instance.push_back(Method);
}

// Load factory methods
for (unsigned I = 0; I != NumFactoryMethods; ++I) {
if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>(
F,
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)))
F, endian::readNext<uint32_t, llvm::endianness::little>(d)))
Result.Factory.push_back(Method);
}

Expand Down Expand Up @@ -1009,8 +1006,7 @@ static bool readBit(unsigned &Bits) {
IdentID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) {
using namespace llvm::support;

unsigned RawID =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
unsigned RawID = endian::readNext<uint32_t, llvm::endianness::little>(d);
return Reader.getGlobalIdentifierID(F, RawID >> 1);
}

Expand All @@ -1028,8 +1024,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
unsigned DataLen) {
using namespace llvm::support;

unsigned RawID =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
unsigned RawID = endian::readNext<uint32_t, llvm::endianness::little>(d);
bool IsInteresting = RawID & 0x01;

// Wipe out the "is interesting" bit.
Expand All @@ -1053,9 +1048,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
}

unsigned ObjCOrBuiltinID =
endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
unsigned Bits =
endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
endian::readNext<uint16_t, llvm::endianness::little>(d);
unsigned Bits = endian::readNext<uint16_t, llvm::endianness::little>(d);
bool CPlusPlusOperatorKeyword = readBit(Bits);
bool HasRevertedTokenIDToIdentifier = readBit(Bits);
bool Poisoned = readBit(Bits);
Expand Down Expand Up @@ -1084,7 +1078,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
// definition.
if (HadMacroDefinition) {
uint32_t MacroDirectivesOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
endian::readNext<uint32_t, llvm::endianness::little>(d);
DataLen -= 4;

Reader.addPendingMacro(II, &F, MacroDirectivesOffset);
Expand All @@ -1098,8 +1092,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
SmallVector<uint32_t, 4> DeclIDs;
for (; DataLen > 0; DataLen -= 4)
DeclIDs.push_back(Reader.getGlobalDeclID(
F,
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)));
F, endian::readNext<uint32_t, llvm::endianness::little>(d)));
Reader.SetGloballyVisibleDecls(II, DeclIDs);
}

Expand Down Expand Up @@ -1169,7 +1162,7 @@ ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) {
using namespace llvm::support;

uint32_t ModuleFileID =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
endian::readNext<uint32_t, llvm::endianness::little>(d);
return Reader.getLocalModuleFile(F, ModuleFileID);
}

Expand All @@ -1189,18 +1182,15 @@ ASTDeclContextNameLookupTrait::ReadKey(const unsigned char *d, unsigned) {
case DeclarationName::CXXLiteralOperatorName:
case DeclarationName::CXXDeductionGuideName:
Data = (uint64_t)Reader.getLocalIdentifier(
F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d));
F, endian::readNext<uint32_t, llvm::endianness::little>(d));
break;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
Data =
(uint64_t)Reader
.getLocalSelector(
F,
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(
d))
.getAsOpaquePtr();
Data = (uint64_t)Reader
.getLocalSelector(
F, endian::readNext<uint32_t, llvm::endianness::little>(d))
.getAsOpaquePtr();
break;
case DeclarationName::CXXOperatorName:
Data = *d++; // OverloadedOperatorKind
Expand All @@ -1223,8 +1213,7 @@ void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type,
using namespace llvm::support;

for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) {
uint32_t LocalID =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
uint32_t LocalID = endian::readNext<uint32_t, llvm::endianness::little>(d);
Val.insert(Reader.getGlobalDeclID(F, LocalID));
}
}
Expand Down Expand Up @@ -2033,10 +2022,9 @@ HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) {
using namespace llvm::support;

internal_key_type ikey;
ikey.Size =
off_t(endian::readNext<uint64_t, llvm::endianness::little, unaligned>(d));
ikey.ModTime = time_t(
endian::readNext<uint64_t, llvm::endianness::little, unaligned>(d));
ikey.Size = off_t(endian::readNext<uint64_t, llvm::endianness::little>(d));
ikey.ModTime =
time_t(endian::readNext<uint64_t, llvm::endianness::little>(d));
ikey.Filename = (const char *)d;
ikey.Imported = true;
return ikey;
Expand Down Expand Up @@ -2064,9 +2052,9 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
HFI.DirInfo = (Flags >> 1) & 0x07;
HFI.IndexHeaderMapHeader = Flags & 0x01;
HFI.ControllingMacroID = Reader.getGlobalIdentifierID(
M, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d));
M, endian::readNext<uint32_t, llvm::endianness::little>(d));
if (unsigned FrameworkOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)) {
endian::readNext<uint32_t, llvm::endianness::little>(d)) {
// The framework offset is 1 greater than the actual offset,
// since 0 is used as an indicator for "no framework name".
StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
Expand All @@ -2077,7 +2065,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
"Wrong data length in HeaderFileInfo deserialization");
while (d != End) {
uint32_t LocalSMID =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
endian::readNext<uint32_t, llvm::endianness::little>(d);
auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 7);
LocalSMID >>= 3;

Expand Down Expand Up @@ -4085,9 +4073,8 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const {
// how it goes...
using namespace llvm::support;
ModuleKind Kind = static_cast<ModuleKind>(
endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data));
uint16_t Len =
endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint8_t, llvm::endianness::little>(Data));
uint16_t Len = endian::readNext<uint16_t, llvm::endianness::little>(Data);
StringRef Name = StringRef((const char*)Data, Len);
Data += Len;
ModuleFile *OM = (Kind == MK_PrebuiltModule || Kind == MK_ExplicitModule ||
Expand All @@ -4103,21 +4090,21 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const {
}

SourceLocation::UIntTy SLocOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint32_t, llvm::endianness::little>(Data);
uint32_t IdentifierIDOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint32_t, llvm::endianness::little>(Data);
uint32_t MacroIDOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint32_t, llvm::endianness::little>(Data);
uint32_t PreprocessedEntityIDOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint32_t, llvm::endianness::little>(Data);
uint32_t SubmoduleIDOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint32_t, llvm::endianness::little>(Data);
uint32_t SelectorIDOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint32_t, llvm::endianness::little>(Data);
uint32_t DeclIDOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint32_t, llvm::endianness::little>(Data);
uint32_t TypeIndexOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
endian::readNext<uint32_t, llvm::endianness::little>(Data);

auto mapOffset = [&](uint32_t Offset, uint32_t BaseOffset,
RemapBuilder &Remap) {
Expand Down Expand Up @@ -9798,7 +9785,7 @@ void ASTReader::finishPendingActions() {
!NonConstDefn->isLateTemplateParsed() &&
// We only perform ODR checks for decls not in the explicit
// global module fragment.
!FD->shouldSkipCheckingODR() &&
!shouldSkipCheckingODR(FD) &&
FD->getODRHash() != NonConstDefn->getODRHash()) {
if (!isa<CXXMethodDecl>(FD)) {
PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn);
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
Reader.mergeDefinitionVisibility(OldDef, ED);
// We don't want to check the ODR hash value for declarations from global
// module fragment.
if (!ED->shouldSkipCheckingODR() &&
if (!shouldSkipCheckingODR(ED) &&
OldDef->getODRHash() != ED->getODRHash())
Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
} else {
Expand Down Expand Up @@ -868,7 +868,7 @@ void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) {
VisitRecordDeclImpl(RD);
// We should only reach here if we're in C/Objective-C. There is no
// global module fragment.
assert(!RD->shouldSkipCheckingODR());
assert(!shouldSkipCheckingODR(RD));
RD->setODRHash(Record.readInt());

// Maintain the invariant of a redeclaration chain containing only
Expand Down Expand Up @@ -2155,7 +2155,7 @@ void ASTDeclReader::MergeDefinitionData(
}

// We don't want to check ODR for decls in the global module fragment.
if (MergeDD.Definition->shouldSkipCheckingODR())
if (shouldSkipCheckingODR(MergeDD.Definition))
return;

if (D->getODRHash() != MergeDD.ODRHash) {
Expand Down Expand Up @@ -3530,7 +3530,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
// same template specialization into the same CXXRecordDecl.
auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext());
if (MergedDCIt != Reader.MergedDeclContexts.end() &&
!D->shouldSkipCheckingODR() && MergedDCIt->second == D->getDeclContext())
!shouldSkipCheckingODR(D) && MergedDCIt->second == D->getDeclContext())
Reader.PendingOdrMergeChecks.push_back(D);

return FindExistingResult(Reader, D, /*Existing=*/nullptr,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6188,7 +6188,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {

BitsPacker DefinitionBits;

bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR();
bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D);
DefinitionBits.addBit(ShouldSkipCheckingODR);

#define FIELD(Name, Width, Merge) \
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
BitsPacker EnumDeclBits;
EnumDeclBits.addBits(D->getNumPositiveBits(), /*BitWidth=*/8);
EnumDeclBits.addBits(D->getNumNegativeBits(), /*BitWidth=*/8);
bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR();
bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D);
EnumDeclBits.addBit(ShouldSkipCheckingODR);
EnumDeclBits.addBit(D->isScoped());
EnumDeclBits.addBit(D->isScopedUsingClassTag());
Expand All @@ -552,7 +552,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
!D->isTopLevelDeclInObjCContainer() &&
!CXXRecordDecl::classofKind(D->getKind()) &&
!D->getIntegerTypeSourceInfo() && !D->getMemberSpecializationInfo() &&
!needsAnonymousDeclarationNumber(D) && !D->shouldSkipCheckingODR() &&
!needsAnonymousDeclarationNumber(D) && !shouldSkipCheckingODR(D) &&
D->getDeclName().getNameKind() == DeclarationName::Identifier)
AbbrevToUse = Writer.getDeclEnumAbbrev();

Expand Down Expand Up @@ -718,7 +718,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
// FIXME: stable encoding
FunctionDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), 3);
FunctionDeclBits.addBits((uint32_t)D->getStorageClass(), /*BitWidth=*/3);
bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR();
bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D);
FunctionDeclBits.addBit(ShouldSkipCheckingODR);
FunctionDeclBits.addBit(D->isInlineSpecified());
FunctionDeclBits.addBit(D->isInlined());
Expand Down Expand Up @@ -1559,7 +1559,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() &&
!D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() &&
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
!D->shouldSkipCheckingODR() && !D->hasExtInfo() &&
!shouldSkipCheckingODR(D) && !D->hasExtInfo() &&
!D->isExplicitlyDefaulted()) {
if (D->getTemplatedKind() == FunctionDecl::TK_NonTemplate ||
D->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate ||
Expand Down
12 changes: 4 additions & 8 deletions clang/lib/Serialization/GlobalModuleIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,8 @@ class IdentifierIndexReaderTrait {
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d) {
using namespace llvm::support;
unsigned KeyLen =
endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
unsigned DataLen =
endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
unsigned KeyLen = endian::readNext<uint16_t, llvm::endianness::little>(d);
unsigned DataLen = endian::readNext<uint16_t, llvm::endianness::little>(d);
return std::make_pair(KeyLen, DataLen);
}

Expand All @@ -113,8 +111,7 @@ class IdentifierIndexReaderTrait {

data_type Result;
while (DataLen > 0) {
unsigned ID =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
unsigned ID = endian::readNext<uint32_t, llvm::endianness::little>(d);
Result.push_back(ID);
DataLen -= 4;
}
Expand Down Expand Up @@ -514,8 +511,7 @@ namespace {
// The first bit indicates whether this identifier is interesting.
// That's all we care about.
using namespace llvm::support;
unsigned RawID =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
unsigned RawID = endian::readNext<uint32_t, llvm::endianness::little>(d);
bool IsInteresting = RawID & 0x01;
return std::make_pair(k, IsInteresting);
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Serialization/MultiOnDiskHashTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,11 @@ template<typename Info> class MultiOnDiskHashTable {
storage_type Ptr = Data;

uint32_t BucketOffset =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Ptr);
endian::readNext<uint32_t, llvm::endianness::little>(Ptr);

// Read the list of overridden files.
uint32_t NumFiles =
endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Ptr);
endian::readNext<uint32_t, llvm::endianness::little>(Ptr);
// FIXME: Add a reserve() to TinyPtrVector so that we don't need to make
// an additional copy.
llvm::SmallVector<file_type, 16> OverriddenFiles;
Expand Down
25 changes: 5 additions & 20 deletions clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
//
//===----------------------------------------------------------------------===//
//
// This checker evaluates clang builtin functions.
// This checker evaluates "standalone" clang builtin functions that are not
// just special-cased variants of well-known non-builtin functions.
// Builtin functions like __builtin_memcpy and __builtin_alloca should be
// evaluated by the same checker that handles their non-builtin variant to
// ensure that the two variants are handled consistently.
//
//===----------------------------------------------------------------------===//

Expand Down Expand Up @@ -80,25 +84,6 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
return true;
}

case Builtin::BI__builtin_alloca_with_align:
case Builtin::BI__builtin_alloca: {
SValBuilder &SVB = C.getSValBuilder();
const loc::MemRegionVal R =
SVB.getAllocaRegionVal(CE, C.getLocationContext(), C.blockCount());

// Set the extent of the region in bytes. This enables us to use the SVal
// of the argument directly. If we saved the extent in bits, it'd be more
// difficult to reason about values like symbol*8.
auto Size = Call.getArgSVal(0);
if (auto DefSize = Size.getAs<DefinedOrUnknownSVal>()) {
// This `getAs()` is mostly paranoia, because core.CallAndMessage reports
// undefined function arguments (unless it's disabled somehow).
state = setDynamicExtent(state, R.getRegion(), *DefSize, SVB);
}
C.addTransition(state->BindExpr(CE, LCtx, R));
return true;
}

case Builtin::BI__builtin_dynamic_object_size:
case Builtin::BI__builtin_object_size:
case Builtin::BI__builtin_constant_p: {
Expand Down
89 changes: 49 additions & 40 deletions clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,10 +401,11 @@ class MallocChecker
};

const CallDescriptionMap<CheckFn> FreeingMemFnMap{
{{{"free"}, 1}, &MallocChecker::checkFree},
{{{"if_freenameindex"}, 1}, &MallocChecker::checkIfFreeNameIndex},
{{{"kfree"}, 1}, &MallocChecker::checkFree},
{{{"g_free"}, 1}, &MallocChecker::checkFree},
{{CDM::CLibrary, {"free"}, 1}, &MallocChecker::checkFree},
{{CDM::CLibrary, {"if_freenameindex"}, 1},
&MallocChecker::checkIfFreeNameIndex},
{{CDM::CLibrary, {"kfree"}, 1}, &MallocChecker::checkFree},
{{CDM::CLibrary, {"g_free"}, 1}, &MallocChecker::checkFree},
};

bool isFreeingCall(const CallEvent &Call) const;
Expand All @@ -413,41 +414,46 @@ class MallocChecker
friend class NoOwnershipChangeVisitor;

CallDescriptionMap<CheckFn> AllocatingMemFnMap{
{{{"alloca"}, 1}, &MallocChecker::checkAlloca},
{{{"_alloca"}, 1}, &MallocChecker::checkAlloca},
{{{"malloc"}, 1}, &MallocChecker::checkBasicAlloc},
{{{"malloc"}, 3}, &MallocChecker::checkKernelMalloc},
{{{"calloc"}, 2}, &MallocChecker::checkCalloc},
{{{"valloc"}, 1}, &MallocChecker::checkBasicAlloc},
{{CDM::CLibrary, {"alloca"}, 1}, &MallocChecker::checkAlloca},
{{CDM::CLibrary, {"_alloca"}, 1}, &MallocChecker::checkAlloca},
// The line for "alloca" also covers "__builtin_alloca", but the
// _with_align variant must be listed separately because it takes an
// extra argument:
{{CDM::CLibrary, {"__builtin_alloca_with_align"}, 2},
&MallocChecker::checkAlloca},
{{CDM::CLibrary, {"malloc"}, 1}, &MallocChecker::checkBasicAlloc},
{{CDM::CLibrary, {"malloc"}, 3}, &MallocChecker::checkKernelMalloc},
{{CDM::CLibrary, {"calloc"}, 2}, &MallocChecker::checkCalloc},
{{CDM::CLibrary, {"valloc"}, 1}, &MallocChecker::checkBasicAlloc},
{{CDM::CLibrary, {"strndup"}, 2}, &MallocChecker::checkStrdup},
{{CDM::CLibrary, {"strdup"}, 1}, &MallocChecker::checkStrdup},
{{{"_strdup"}, 1}, &MallocChecker::checkStrdup},
{{{"kmalloc"}, 2}, &MallocChecker::checkKernelMalloc},
{{{"if_nameindex"}, 1}, &MallocChecker::checkIfNameIndex},
{{CDM::CLibrary, {"_strdup"}, 1}, &MallocChecker::checkStrdup},
{{CDM::CLibrary, {"kmalloc"}, 2}, &MallocChecker::checkKernelMalloc},
{{CDM::CLibrary, {"if_nameindex"}, 1}, &MallocChecker::checkIfNameIndex},
{{CDM::CLibrary, {"wcsdup"}, 1}, &MallocChecker::checkStrdup},
{{CDM::CLibrary, {"_wcsdup"}, 1}, &MallocChecker::checkStrdup},
{{{"g_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
{{{"g_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
{{{"g_try_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
{{{"g_try_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
{{{"g_memdup"}, 2}, &MallocChecker::checkGMemdup},
{{{"g_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
{{{"g_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
{{{"g_try_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
{{{"g_try_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
{{CDM::CLibrary, {"g_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
{{CDM::CLibrary, {"g_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
{{CDM::CLibrary, {"g_try_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
{{CDM::CLibrary, {"g_try_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
{{CDM::CLibrary, {"g_memdup"}, 2}, &MallocChecker::checkGMemdup},
{{CDM::CLibrary, {"g_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
{{CDM::CLibrary, {"g_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
{{CDM::CLibrary, {"g_try_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
{{CDM::CLibrary, {"g_try_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
};

CallDescriptionMap<CheckFn> ReallocatingMemFnMap{
{{{"realloc"}, 2},
{{CDM::CLibrary, {"realloc"}, 2},
std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
{{{"reallocf"}, 2},
{{CDM::CLibrary, {"reallocf"}, 2},
std::bind(&MallocChecker::checkRealloc, _1, _2, _3, true)},
{{{"g_realloc"}, 2},
{{CDM::CLibrary, {"g_realloc"}, 2},
std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
{{{"g_try_realloc"}, 2},
{{CDM::CLibrary, {"g_try_realloc"}, 2},
std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
{{{"g_realloc_n"}, 3}, &MallocChecker::checkReallocN},
{{{"g_try_realloc_n"}, 3}, &MallocChecker::checkReallocN},
{{CDM::CLibrary, {"g_realloc_n"}, 3}, &MallocChecker::checkReallocN},
{{CDM::CLibrary, {"g_try_realloc_n"}, 3}, &MallocChecker::checkReallocN},

// NOTE: the following CallDescription also matches the C++ standard
// library function std::getline(); the callback will filter it out.
Expand Down Expand Up @@ -1259,9 +1265,6 @@ static bool isStandardRealloc(const CallEvent &Call) {
assert(FD);
ASTContext &AC = FD->getASTContext();

if (isa<CXXMethodDecl>(FD))
return false;

return FD->getDeclaredReturnType().getDesugaredType(AC) == AC.VoidPtrTy &&
FD->getParamDecl(0)->getType().getDesugaredType(AC) == AC.VoidPtrTy &&
FD->getParamDecl(1)->getType().getDesugaredType(AC) ==
Expand All @@ -1273,9 +1276,6 @@ static bool isGRealloc(const CallEvent &Call) {
assert(FD);
ASTContext &AC = FD->getASTContext();

if (isa<CXXMethodDecl>(FD))
return false;

return FD->getDeclaredReturnType().getDesugaredType(AC) == AC.VoidPtrTy &&
FD->getParamDecl(0)->getType().getDesugaredType(AC) == AC.VoidPtrTy &&
FD->getParamDecl(1)->getType().getDesugaredType(AC) ==
Expand All @@ -1284,14 +1284,14 @@ static bool isGRealloc(const CallEvent &Call) {

void MallocChecker::checkRealloc(const CallEvent &Call, CheckerContext &C,
bool ShouldFreeOnFail) const {
// HACK: CallDescription currently recognizes non-standard realloc functions
// as standard because it doesn't check the type, or wether its a non-method
// function. This should be solved by making CallDescription smarter.
// Mind that this came from a bug report, and all other functions suffer from
// this.
// https://bugs.llvm.org/show_bug.cgi?id=46253
// Ignore calls to functions whose type does not match the expected type of
// either the standard realloc or g_realloc from GLib.
// FIXME: Should we perform this kind of checking consistently for each
// function? If yes, then perhaps extend the `CallDescription` interface to
// handle this.
if (!isStandardRealloc(Call) && !isGRealloc(Call))
return;

ProgramStateRef State = C.getState();
State = ReallocMemAux(C, Call, ShouldFreeOnFail, State, AF_Malloc);
State = ProcessZeroAllocCheck(Call, 1, State);
Expand Down Expand Up @@ -1842,9 +1842,18 @@ static ProgramStateRef MallocUpdateRefState(CheckerContext &C, const Expr *E,
return nullptr;

SymbolRef Sym = RetVal->getAsLocSymbol();

// This is a return value of a function that was not inlined, such as malloc()
// or new(). We've checked that in the caller. Therefore, it must be a symbol.
assert(Sym);
// FIXME: In theory this assertion should fail for `alloca()` calls (because
// `AllocaRegion`s are not symbolic); but in practice this does not happen.
// As the current code appears to work correctly, I'm not touching this issue
// now, but it would be good to investigate and clarify this.
// Also note that perhaps the special `AllocaRegion` should be replaced by
// `SymbolicRegion` (or turned into a subclass of `SymbolicRegion`) to enable
// proper tracking of memory allocated by `alloca()` -- and after that change
// this assertion would become valid again.

// Set the symbol's state to Allocated.
return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
Expand Down
36 changes: 24 additions & 12 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ void ModuleDepCollector::addOutputPaths(CowCompilerInvocation &CI,
}
}

void dependencies::resetBenignCodeGenOptions(frontend::ActionKind ProgramAction,
const LangOptions &LangOpts,
CodeGenOptions &CGOpts) {
// TODO: Figure out better way to set options to their default value.
if (ProgramAction == frontend::GenerateModule) {
CGOpts.MainFileName.clear();
CGOpts.DwarfDebugFlags.clear();
}
if (ProgramAction == frontend::GeneratePCH ||
(ProgramAction == frontend::GenerateModule && !LangOpts.ModulesCodegen)) {
CGOpts.DebugCompilationDir.clear();
CGOpts.CoverageCompilationDir.clear();
CGOpts.CoverageDataFile.clear();
CGOpts.CoverageNotesFile.clear();
CGOpts.ProfileInstrumentUsePath.clear();
CGOpts.SampleProfileFile.clear();
CGOpts.ProfileRemappingFile.clear();
}
}

static CowCompilerInvocation
makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
CI.resetNonModularOptions();
Expand All @@ -167,18 +187,8 @@ makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
// LLVM options are not going to affect the AST
CI.getFrontendOpts().LLVMArgs.clear();

// TODO: Figure out better way to set options to their default value.
CI.getCodeGenOpts().MainFileName.clear();
CI.getCodeGenOpts().DwarfDebugFlags.clear();
if (!CI.getLangOpts().ModulesCodegen) {
CI.getCodeGenOpts().DebugCompilationDir.clear();
CI.getCodeGenOpts().CoverageCompilationDir.clear();
CI.getCodeGenOpts().CoverageDataFile.clear();
CI.getCodeGenOpts().CoverageNotesFile.clear();
CI.getCodeGenOpts().ProfileInstrumentUsePath.clear();
CI.getCodeGenOpts().SampleProfileFile.clear();
CI.getCodeGenOpts().ProfileRemappingFile.clear();
}
resetBenignCodeGenOptions(frontend::GenerateModule, CI.getLangOpts(),
CI.getCodeGenOpts());

// Map output paths that affect behaviour to "-" so their existence is in the
// context hash. The final path will be computed in addOutputPaths.
Expand Down Expand Up @@ -342,6 +352,8 @@ static bool needsModules(FrontendInputFile FIF) {

void ModuleDepCollector::applyDiscoveredDependencies(CompilerInvocation &CI) {
CI.clearImplicitModuleBuildOptions();
resetBenignCodeGenOptions(CI.getFrontendOpts().ProgramAction,
CI.getLangOpts(), CI.getCodeGenOpts());

if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) {
Preprocessor &PP = ScanInstance.getPreprocessor();
Expand Down
8 changes: 7 additions & 1 deletion clang/test/AST/Interp/vectors.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -verify=ref,both %s

// both-no-diagnostics
// ref-no-diagnostics

typedef int __attribute__((vector_size(16))) VI4;
constexpr VI4 A = {1,2,3,4};
Expand All @@ -20,3 +20,9 @@ namespace Vector {
}
constexpr auto v2 = g(4);
}

/// FIXME: We need to support BitCasts between vector types.
namespace {
typedef float __attribute__((vector_size(16))) VI42;
constexpr VI42 A2 = A; // expected-error {{must be initialized by a constant expression}}
}
1 change: 1 addition & 0 deletions clang/test/AST/ast-dump-attr-json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ __thread __attribute__ ((tls_model ("local-exec"))) int tls_model_var;
// CHECK-NEXT: "tokLen": 11
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: "isUsed": true,
// CHECK-NEXT: "name": "global_decl",
// CHECK-NEXT: "mangledName": "global_decl",
// CHECK-NEXT: "type": {
Expand Down
6 changes: 4 additions & 2 deletions clang/test/Analysis/Inputs/system-header-simulator-cxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,7 @@ using ostream = basic_ostream<char>;
extern std::ostream cout;

ostream &operator<<(ostream &, const string &);

#if __cplusplus >= 202002L
template <class T>
ostream &operator<<(ostream &, const std::unique_ptr<T> &);
Expand All @@ -1122,11 +1123,12 @@ istream &getline(istream &, string &, char);
istream &getline(istream &, string &);
} // namespace std

#ifdef TEST_INLINABLE_ALLOCATORS
namespace std {
void *malloc(size_t);
void free(void *);
}
} // namespace std

#ifdef TEST_INLINABLE_ALLOCATORS
void* operator new(std::size_t size, const std::nothrow_t&) throw() { return std::malloc(size); }
void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return std::malloc(size); }
void operator delete(void* ptr, const std::nothrow_t&) throw() { std::free(ptr); }
Expand Down
24 changes: 16 additions & 8 deletions clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,optin.cplusplus.UninitializedObject \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
// RUN: -std=c++11 -verify %s

// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,optin.cplusplus.UninitializedObject \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
// RUN: -std=c++11 -verify %s

Expand Down Expand Up @@ -316,7 +316,10 @@ void fCyclicPointerTest2() {

// Void pointer tests are mainly no-crash tests.

void *malloc(int size);
typedef __typeof(sizeof(int)) size_t;

void *calloc(size_t nmemb, size_t size);
void free(void *p);

class VoidPointerTest1 {
void *vptr;
Expand All @@ -328,8 +331,9 @@ class VoidPointerTest1 {
};

void fVoidPointerTest1() {
void *vptr = malloc(sizeof(int));
void *vptr = calloc(1, sizeof(int));
VoidPointerTest1(vptr, char());
free(vptr);
}

class VoidPointerTest2 {
Expand All @@ -342,8 +346,9 @@ class VoidPointerTest2 {
};

void fVoidPointerTest2() {
void *vptr = malloc(sizeof(int));
void *vptr = calloc(1, sizeof(int));
VoidPointerTest2(&vptr, char());
free(vptr);
}

class VoidPointerRRefTest1 {
Expand All @@ -359,8 +364,9 @@ upon returning to the caller. This will be a dangling reference}}
};

void fVoidPointerRRefTest1() {
void *vptr = malloc(sizeof(int));
void *vptr = calloc(1, sizeof(int));
VoidPointerRRefTest1(vptr, char());
free(vptr);
}

class VoidPointerRRefTest2 {
Expand All @@ -376,8 +382,9 @@ upon returning to the caller. This will be a dangling reference}}
};

void fVoidPointerRRefTest2() {
void *vptr = malloc(sizeof(int));
void *vptr = calloc(1, sizeof(int));
VoidPointerRRefTest2(&vptr, char());
free(vptr);
}

class VoidPointerLRefTest {
Expand All @@ -393,8 +400,9 @@ upon returning to the caller. This will be a dangling reference}}
};

void fVoidPointerLRefTest() {
void *vptr = malloc(sizeof(int));
void *vptr = calloc(1, sizeof(int));
VoidPointerLRefTest(vptr, char());
free(vptr);
}

struct CyclicVoidPointerTest {
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Analysis/exercise-ps.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 %s -verify -Wno-error=implicit-function-declaration \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-checker=core,unix.Malloc \
// RUN: -analyzer-config core.CallAndMessage:ArgPointeeInitializedness=true
//
// Just exercise the analyzer on code that has at one point caused issues
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Analysis/explain-svals.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -verify %s \
// RUN: -analyzer-checker=core.builtin \
// RUN: -analyzer-checker=debug.ExprInspection \
// RUN: -analyzer-checker=unix.cstring \
// RUN: -analyzer-checker=unix.Malloc \
// RUN: -analyzer-config display-checker-name=false

typedef unsigned long size_t;
Expand Down
24 changes: 24 additions & 0 deletions clang/test/Analysis/malloc-std-namespace.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -analyzer-output=text %s

// This file tests that unix.Malloc can handle C++ code where e.g. malloc and
// free are declared within the namespace 'std' by the header <cstdlib>.

#include "Inputs/system-header-simulator-cxx.h"

void leak() {
int *p = static_cast<int*>(std::malloc(sizeof(int))); // expected-note{{Memory is allocated}}
} // expected-warning{{Potential leak of memory pointed to by 'p'}}
// expected-note@-1{{Potential leak of memory pointed to by 'p'}}

void no_leak() {
int *p = static_cast<int*>(std::malloc(sizeof(int)));
std::free(p); // no-warning
}

void invalid_free() {
int i;
int *p = &i;
//expected-note@+2{{Argument to free() is the address of the local variable 'i', which is not memory allocated by malloc()}}
//expected-warning@+1{{Argument to free() is the address of the local variable 'i', which is not memory allocated by malloc()}}
std::free(p);
}
11 changes: 11 additions & 0 deletions clang/test/Analysis/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,17 @@ void allocaFree(void) {
free(p); // expected-warning {{Memory allocated by alloca() should not be deallocated}}
}

void allocaFreeBuiltin(void) {
int *p = __builtin_alloca(sizeof(int));
free(p); // expected-warning {{Memory allocated by alloca() should not be deallocated}}
}

void allocaFreeBuiltinAlign(void) {
int *p = __builtin_alloca_with_align(sizeof(int), 64);
free(p); // expected-warning {{Memory allocated by alloca() should not be deallocated}}
}


int* mallocEscapeRet(void) {
int *p = malloc(12);
return p; // no warning
Expand Down
11 changes: 11 additions & 0 deletions clang/test/Analysis/malloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,14 @@ void *realloc(void **ptr, size_t size) { realloc(ptr, size); } // no-crash
namespace pr46253_paramty2{
void *realloc(void *ptr, int size) { realloc(ptr, size); } // no-crash
} // namespace pr46253_paramty2

namespace pr81597 {
struct S {};
struct T {
void free(const S& s);
};
void f(T& t) {
S s;
t.free(s); // no-warning: This is not the free you are looking for...
}
} // namespace pr81597
2 changes: 1 addition & 1 deletion clang/test/Analysis/stack-addr-ps.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -fblocks -verify %s

int* f1(void) {
int x = 0;
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Analysis/stackaddrleak.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -std=c99 -Dbool=_Bool -Wno-bool-conversion %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -x c++ -Wno-bool-conversion %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -std=c99 -Dbool=_Bool -Wno-bool-conversion %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -x c++ -Wno-bool-conversion %s

typedef __INTPTR_TYPE__ intptr_t;
char const *p;
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CXX/over/over.built/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ struct A{};

template <typename T, typename U>
auto Test(T* pt, U* pu) {
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '*'
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '*'
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
(void)*pt;

// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '++'
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '++'
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
(void)(++pt);

Expand Down
28 changes: 28 additions & 0 deletions clang/test/ClangScanDeps/removed-args.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,31 @@
// CHECK-NOT: "-fmodules-prune-interval=
// CHECK-NOT: "-fmodules-prune-after=
// CHECK: ],

// Check for removed args for PCH invocations.

// RUN: split-file %s %t
// RUN: sed "s|DIR|%/t|g" %t/cdb-pch.json.template > %t/cdb-pch.json
// RUN: clang-scan-deps -compilation-database %t/cdb-pch.json -format experimental-full > %t/result-pch.json
// RUN: cat %t/result-pch.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t -check-prefix=PCH
//
// PCH-NOT: "-fdebug-compilation-dir="
// PCH-NOT: "-fcoverage-compilation-dir="
// PCH-NOT: "-coverage-notes-file
// PCH-NOT: "-coverage-data-file
// PCH-NOT: "-fprofile-instrument-use-path
// PCH-NOT: "-include"
// PCH-NOT: "-fmodules-cache-path=
// PCH-NOT: "-fmodules-validate-once-per-build-session"
// PCH-NOT: "-fbuild-session-timestamp=
// PCH-NOT: "-fmodules-prune-interval=
// PCH-NOT: "-fmodules-prune-after=

//--- cdb-pch.json.template
[
{
"directory": "DIR",
"command": "clang -x c-header DIR/header.h -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -fdebug-compilation-dir=DIR/debug -fcoverage-compilation-dir=DIR/coverage -ftest-coverage -fprofile-instr-use=DIR/tu.profdata -o DIR/header.h.pch -serialize-diagnostics DIR/header.h.pch.diag ",
"file": "DIR/header.h.pch"
}
]
18 changes: 18 additions & 0 deletions clang/test/CodeGen/bitfield-access-unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,24 @@ struct G {
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:4
// CHECK-NEXT: ]>

struct __attribute__((aligned(8))) H {
char a;
unsigned b : 24; // on expensive alignment we want this to stay 24
unsigned c __attribute__((aligned(8))); // Think 'long long' or lp64 ptr
} h;
// CHECK-LABEL: LLVMType:%struct.H =
// LAYOUT-FLEX-SAME: type <{ i8, i32, [3 x i8], i32, [4 x i8] }>
// LAYOUT-STRICT-SAME: type { i8, [3 x i8], [4 x i8], i32, [4 x i8] }
// LAYOUT-DWN32-FLEX-SAME: type <{ i8, i32, [3 x i8], i32, [4 x i8] }>
// LAYOUT-DWN32-STRICT-SAME: type { i8, [3 x i8], [4 x i8], i32, [4 x i8] }
// CHECK: BitFields:[
// LAYOUT-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:0 StorageSize:32 StorageOffset:1
// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:0 StorageSize:24 StorageOffset:1

// LAYOUT-DWN32-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:0 StorageSize:32 StorageOffset:1
// LAYOUT-DWN32-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:0 StorageSize:24 StorageOffset:1
// CHECK-NEXT: ]>

#if _LP64
struct A64 {
int a : 16;
Expand Down
47 changes: 46 additions & 1 deletion clang/test/CodeGenCXX/control-flow-in-stmt-expr.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 --std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 --std=c++20 -fexceptions -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefixes=EH %s
// RUN: %clang_cc1 --std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefixes=NOEH,CHECK %s

struct Printy {
Printy(const char *name) : name(name) {}
Expand Down Expand Up @@ -349,6 +350,34 @@ void NewArrayInit() {
// CHECK-NEXT: br label %return
}

void DestroyInConditionalCleanup() {
// EH-LABEL: DestroyInConditionalCleanupv()
// NOEH-LABEL: DestroyInConditionalCleanupv()
struct A {
A() {}
~A() {}
};

struct Value {
Value(A) {}
~Value() {}
};

struct V2 {
Value K;
Value V;
};
// Verify we use conditional cleanups.
(void)(foo() ? V2{A(), A()} : V2{A(), A()});
// NOEH: cond.true:
// NOEH: call void @_ZZ27DestroyInConditionalCleanupvEN1AC1Ev
// NOEH: store ptr %{{.*}}, ptr %cond-cleanup.save

// EH: cond.true:
// EH: invoke void @_ZZ27DestroyInConditionalCleanupvEN1AC1Ev
// EH: store ptr %{{.*}}, ptr %cond-cleanup.save
}

void ArrayInitWithContinue() {
// CHECK-LABEL: @_Z21ArrayInitWithContinuev
// Verify that we start to emit the array destructor.
Expand All @@ -362,3 +391,19 @@ void ArrayInitWithContinue() {
})};
}
}

struct [[clang::trivial_abi]] HasTrivialABI {
HasTrivialABI();
~HasTrivialABI();
};
void AcceptTrivialABI(HasTrivialABI, int);
void TrivialABI() {
// CHECK-LABEL: define dso_local void @_Z10TrivialABIv()
AcceptTrivialABI(HasTrivialABI(), ({
if (foo()) return;
// CHECK: if.then:
// CHECK-NEXT: call void @_ZN13HasTrivialABID1Ev
// CHECK-NEXT: br label %return
0;
}));
}
31 changes: 26 additions & 5 deletions clang/test/CodeGenCXX/module-funcs-from-imports.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ int func_in_gmf_not_called() {
return 44;
}

template <class T>
class A {
public:
__attribute__((always_inline))
inline constexpr int getValue() {
return 43;
}

inline constexpr int getValue2() {
return 43;
}
};

extern template class A<char>;

//--- M.cppm
module;
#include "foo.h"
Expand All @@ -47,17 +62,21 @@ int always_inline_func() {
return 45;
}

export using ::A;

//--- Use.cpp
import M;
int use() {
return exported_func() + always_inline_func();
A<char> a;
return exported_func() + always_inline_func() +
a.getValue() + a.getValue2();
}

// Checks that none of the function (except the always_inline_func) in the importees
// are generated in the importer's code.
// CHECK-O0: define{{.*}}_Z3usev(
// CHECK-O0: declare{{.*}}_ZW1M13exported_funcv(
// CHECK-O0: define{{.*}}available_externally{{.*}}_ZW1M18always_inline_funcv(
// CHECK-O0: declare{{.*}}_ZW1M18always_inline_funcv(
// CHECK-O0: define{{.*}}@_ZN1AIcE8getValueEv(
// CHECK-O0: declare{{.*}}@_ZN1AIcE9getValue2Ev(
// CHECK-O0-NOT: func_in_gmf
// CHECK-O0-NOT: func_in_gmf_not_called
// CHECK-O0-NOT: non_exported_func
Expand All @@ -68,7 +87,9 @@ int use() {
// O0 to keep consistent ABI.
// CHECK-O1: define{{.*}}_Z3usev(
// CHECK-O1: declare{{.*}}_ZW1M13exported_funcv(
// CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M18always_inline_funcv(
// CHECK-O1: declare{{.*}}_ZW1M18always_inline_funcv(
// CHECK-O1: define{{.*}}@_ZN1AIcE8getValueEv(
// CHECK-O1: declare{{.*}}@_ZN1AIcE9getValue2Ev(
// CHECK-O1-NOT: func_in_gmf
// CHECK-O1-NOT: func_in_gmf_not_called
// CHECK-O1-NOT: non_exported_func
Expand Down
370 changes: 244 additions & 126 deletions clang/test/CodeGenHLSL/builtins/any.hlsl

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions clang/test/Modules/hashing-decls-in-exprs-from-gmf-2.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: split-file %s %t
//
// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/A.cppm -emit-module-interface -o %t/A.pcm
// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/test.cpp -fprebuilt-module-path=%t -fsyntax-only -verify

//--- header.h
#pragma once
template <class _Tp>
class Optional {};

template <class _Tp>
concept C = requires(const _Tp& __t) {
[]<class _Up>(const Optional<_Up>&) {}(__t);
};

//--- func.h
#include "header.h"
template <C T>
void func() {}

//--- test_func.h
#include "func.h"

inline void test_func() {
func<Optional<int>>();
}

//--- A.cppm
module;
#include "header.h"
#include "test_func.h"
export module A;
export using ::test_func;

//--- test.cpp
// expected-no-diagnostics
import A;
#include "test_func.h"

void test() {
test_func();
}
3 changes: 1 addition & 2 deletions clang/test/OpenMP/ompx_attributes_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,5 @@ void func() {
// NVIDIA: "omp_target_thread_limit"="45"
// NVIDIA: "omp_target_thread_limit"="17"
// NVIDIA: !{ptr @__omp_offloading[[HASH1:.*]]_l16, !"maxntidx", i32 20}
// NVIDIA: !{ptr @__omp_offloading[[HASH2:.*]]_l18, !"minctasm", i32 90}
// NVIDIA: !{ptr @__omp_offloading[[HASH2]]_l18, !"maxntidx", i32 45}
// NVIDIA: !{ptr @__omp_offloading[[HASH2:.*]]_l18, !"maxntidx", i32 45}
// NVIDIA: !{ptr @__omp_offloading[[HASH3:.*]]_l20, !"maxntidx", i32 17}
2 changes: 1 addition & 1 deletion clang/test/Sema/alias-unused-win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extern "C" {
static int f(void) { return 42; } // cxx-warning{{unused function 'f'}}
int g(void) __attribute__((alias("f")));

static int foo [] = { 42, 0xDEAD }; // cxx-warning{{variable 'foo' is not needed and will not be emitted}}
static int foo [] = { 42, 0xDEAD };
extern typeof(foo) bar __attribute__((unused, alias("foo")));

static int __attribute__((overloadable)) f0(int x) { return x; } // expected-warning{{unused function 'f0'}}
Expand Down
16 changes: 9 additions & 7 deletions clang/test/Sema/alias-unused.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,26 @@ extern typeof(foo) bar __attribute__((unused, alias("foo")));
/// We report a warning in C++ mode because the internal linkage `resolver` gets
/// mangled as it does not have a language linkage. GCC does not mangle
/// `resolver` or report a warning.
static int (*resolver(void))(void) { return f; } // expected-warning{{unused function 'resolver'}}
static int (*resolver(void))(void) { return f; } // cxx-warning{{unused function 'resolver'}}
int ifunc(void) __attribute__((ifunc("resolver")));

static int __attribute__((overloadable)) f0(int x) { return x; } // expected-warning{{unused function 'f0'}}
static int __attribute__((overloadable)) f0(int x) { return x; }
static float __attribute__((overloadable)) f0(float x) { return x; } // expected-warning{{unused function 'f0'}}
int g0(void) __attribute__((alias("_ZL2f0i")));

#ifdef __cplusplus
static int f1() { return 42; } // expected-warning{{unused function 'f1'}}
static int f1() { return 42; }
int g1(void) __attribute__((alias("_ZL2f1v")));
}

static int f2(int) { return 42; } // expected-warning{{unused function 'f2'}}
static int f2() { return 42; } // expected-warning{{unused function 'f2'}}
/// We demangle alias/ifunc target and mark all found functions as used.

static int f2(int) { return 42; } // cxx-warning{{unused function 'f2'}}
static int f2() { return 42; }
int g2() __attribute__((alias("_ZL2f2v")));

static int (*resolver1())() { return f; } // expected-warning{{unused function 'resolver1'}}
static int (*resolver1(int))() { return f; } // expected-warning{{unused function 'resolver1'}}
static int (*resolver1())() { return f; } // cxx-warning{{unused function 'resolver1'}}
static int (*resolver1(int))() { return f; }
int ifunc1() __attribute__((ifunc("_ZL9resolver1i")));

/// TODO: We should report "unused function" for f3(int).
Expand Down
23 changes: 23 additions & 0 deletions clang/test/SemaCXX/PR84020.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: %clang_cc1 -std=c++20 -verify %s
// RUN: %clang_cc1 -std=c++23 -verify %s
// expected-no-diagnostics

struct B {
template <typename S>
void foo();

void bar();
};

template <typename T, typename S>
struct A : T {
auto foo() {
static_assert(requires { T::template foo<S>(); });
static_assert(requires { T::bar(); });
}
};

int main() {
A<B, double> a;
a.foo();
}
10 changes: 10 additions & 0 deletions clang/test/SemaCXX/overloaded-operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,3 +682,13 @@ namespace nw{
}
}
#endif

#if __cplusplus >= 201703L
namespace GH88329 {

template <auto T> struct A {};
template <auto T> A<*T> operator *() { return {}; }
// expected-error@-1 {{overloaded 'operator*' must have at least one parameter of class or enumeration type}}
}

#endif
52 changes: 52 additions & 0 deletions clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3098,6 +3098,58 @@ TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
});
}

// Check that the `std::strong_ordering` object returned by builtin `<=>` has a
// correctly modeled result object location.
TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
std::string Code = R"(
namespace std {
// This is the minimal definition required to get
// `Sema::CheckComparisonCategoryType()` to accept this fake.
struct strong_ordering {
enum class ordering { less, equal, greater };
ordering o;
static const strong_ordering less;
static const strong_ordering equivalent;
static const strong_ordering equal;
static const strong_ordering greater;
};

inline constexpr strong_ordering strong_ordering::less =
{ strong_ordering::ordering::less };
inline constexpr strong_ordering strong_ordering::equal =
{ strong_ordering::ordering::equal };
inline constexpr strong_ordering strong_ordering::equivalent =
{ strong_ordering::ordering::equal };
inline constexpr strong_ordering strong_ordering::greater =
{ strong_ordering::ordering::greater };
}
void target(int i, int j) {
auto ordering = i <=> j;
// [[p]]
}
)";
using ast_matchers::binaryOperator;
using ast_matchers::hasOperatorName;
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 *Spaceship = selectFirst<BinaryOperator>(
"op",
match(binaryOperator(hasOperatorName("<=>")).bind("op"), ASTCtx));

EXPECT_EQ(
&Env.getResultObjectLocation(*Spaceship),
&getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "ordering"));
},
LangStandard::lang_cxx20);
}

TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
std::string Code = R"(
namespace std {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// RUN: %clangxx %s -pie -fPIE -o %t && %run %t
// RUN: %clang %s -pie -fPIE -o %t && %run %t
// REQUIRES: x86_64-target-arch

// FIXME: Fails Asan, as expected, with 5lvl page tables.
// UNSUPPORTED: x86_64-target-arch

#include <assert.h>
#include <stdio.h>
#include <sys/mman.h>
Expand Down
32 changes: 32 additions & 0 deletions flang/include/flang/Optimizer/Dialect/FIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -3190,4 +3190,36 @@ def fir_CUDADataTransferOp : fir_Op<"cuda_data_transfer", []> {
}];
}

def fir_CUDAAllocateOp : fir_Op<"cuda_allocate", [AttrSizedOperandSegments,
MemoryEffects<[MemAlloc<DefaultResource>]>]> {
let summary = "Perform the device allocation of data of an allocatable";

let description = [{
The fir.cuda_allocate operation performs the allocation on the device
of the data of an allocatable. The descriptor passed to the operation
is initialized before with the standard flang runtime calls.
}];

let arguments = (ins Arg<AnyRefOrBoxType, "", [MemWrite]>:$box,
Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg,
Optional<AnyIntegerType>:$stream,
Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$pinned,
Arg<Optional<AnyRefOrBoxType>, "", [MemRead]>:$source,
fir_CUDADataAttributeAttr:$cuda_attr,
UnitAttr:$hasStat);

let results = (outs AnyIntegerType:$stat);

let assemblyFormat = [{
$box `:` qualified(type($box))
( `source` `(` $source^ `:` qualified(type($source) )`)` )?
( `errmsg` `(` $errmsg^ `:` type($errmsg) `)` )?
( `stream` `(` $stream^ `:` type($stream) `)` )?
( `pinned` `(` $pinned^ `:` type($pinned) `)` )?
attr-dict `->` type($stat)
}];

let hasVerifier = 1;
}

#endif
1 change: 1 addition & 0 deletions flang/include/flang/Optimizer/Dialect/FIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ def AnyRefOrBoxLike : TypeConstraint<Or<[AnyReferenceLike.predicate,
def AnyRefOrBox : TypeConstraint<Or<[fir_ReferenceType.predicate,
fir_HeapType.predicate, fir_PointerType.predicate,
IsBaseBoxTypePred]>, "any reference or box">;
def AnyRefOrBoxType : Type<AnyRefOrBox.predicate, "any legal ref or box type">;

def AnyShapeLike : TypeConstraint<Or<[fir_ShapeType.predicate,
fir_ShapeShiftType.predicate]>, "any legal shape type">;
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ class ParseTreeDumper {
NODE_ENUM(OmpOrderModifier, Kind)
NODE(parser, OmpProcBindClause)
NODE_ENUM(OmpProcBindClause, Type)
NODE_ENUM(OmpReductionClause, ReductionModifier)
NODE(parser, OmpReductionClause)
NODE(parser, OmpInReductionClause)
NODE(parser, OmpReductionCombiner)
Expand Down
5 changes: 4 additions & 1 deletion flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3552,7 +3552,10 @@ struct OmpReductionOperator {
// variable-name-list)
struct OmpReductionClause {
TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
std::tuple<OmpReductionOperator, OmpObjectList> t;
ENUM_CLASS(ReductionModifier, Inscan, Task, Default)
std::tuple<std::optional<ReductionModifier>, OmpReductionOperator,
OmpObjectList>
t;
};

// OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier:
Expand Down
26 changes: 21 additions & 5 deletions flang/lib/Lower/OpenMP/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1005,12 +1005,28 @@ ProcBind make(const parser::OmpClause::ProcBind &inp,
Reduction make(const parser::OmpClause::Reduction &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpReductionClause
auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t);
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
using wrapped = parser::OmpReductionClause;

CLAUSET_ENUM_CONVERT( //
convert, wrapped::ReductionModifier, Reduction::ReductionModifier,
// clang-format off
MS(Inscan, Inscan)
MS(Task, Task)
MS(Default, Default)
// clang-format on
);

auto &t0 =
std::get<std::optional<parser::OmpReductionClause::ReductionModifier>>(
inp.v.t);
auto &t1 = std::get<parser::OmpReductionOperator>(inp.v.t);
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
return Reduction{
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
/*ReductionModifier=*/std::nullopt,
/*List=*/makeObjects(t1, semaCtx)}};
{/*ReductionModifier=*/t0
? std::make_optional<Reduction::ReductionModifier>(convert(*t0))
: std::nullopt,
/*ReductionIdentifiers=*/{makeReductionOperator(t1, semaCtx)},
/*List=*/makeObjects(t2, semaCtx)}};
}

// Relaxed: empty
Expand Down
5 changes: 5 additions & 0 deletions flang/lib/Lower/OpenMP/ReductionProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,11 @@ void ReductionProcessor::addDeclareReduction(
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
*reductionSymbols) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

if (std::get<std::optional<omp::clause::Reduction::ReductionModifier>>(
reduction.t))
TODO(currentLocation, "Reduction modifiers are not supported");

mlir::omp::DeclareReductionOp decl;
const auto &redOperatorList{
std::get<omp::clause::Reduction::ReductionIdentifiers>(reduction.t)};
Expand Down
19 changes: 19 additions & 0 deletions flang/lib/Optimizer/Dialect/FIROps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3993,6 +3993,25 @@ mlir::LogicalResult fir::CUDAKernelOp::verify() {
return mlir::success();
}

mlir::LogicalResult fir::CUDAAllocateOp::verify() {
if (getPinned() && getStream())
return emitOpError("pinned and stream cannot appears at the same time");
if (!fir::unwrapRefType(getBox().getType()).isa<fir::BaseBoxType>())
return emitOpError(
"expect box to be a reference to/or a class or box type value");
if (getSource() &&
!fir::unwrapRefType(getSource().getType()).isa<fir::BaseBoxType>())
return emitOpError(
"expect source to be a reference to/or a class or box type value");
if (getErrmsg() &&
!fir::unwrapRefType(getErrmsg().getType()).isa<fir::BoxType>())
return emitOpError(
"expect errmsg to be a reference to/or a box type value");
if (getErrmsg() && !getHasStat())
return emitOpError("expect stat attribute when errmsg is provided");
return mlir::success();
}

//===----------------------------------------------------------------------===//
// FIROpsDialect
//===----------------------------------------------------------------------===//
Expand Down
5 changes: 5 additions & 0 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ TYPE_PARSER(construct<OmpReductionOperator>(Parser<DefinedOperator>{}) ||
construct<OmpReductionOperator>(Parser<ProcedureDesignator>{}))

TYPE_PARSER(construct<OmpReductionClause>(
maybe(
("INSCAN" >> pure(OmpReductionClause::ReductionModifier::Inscan) ||
"TASK" >> pure(OmpReductionClause::ReductionModifier::Task) ||
"DEFAULT" >> pure(OmpReductionClause::ReductionModifier::Default)) /
","),
Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))

// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
Expand Down
4 changes: 4 additions & 0 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2090,6 +2090,8 @@ class UnparseVisitor {
Walk(":", x.step);
}
void Unparse(const OmpReductionClause &x) {
Walk(std::get<std::optional<OmpReductionClause::ReductionModifier>>(x.t),
",");
Walk(std::get<OmpReductionOperator>(x.t));
Put(":");
Walk(std::get<OmpObjectList>(x.t));
Expand Down Expand Up @@ -2727,6 +2729,8 @@ class UnparseVisitor {
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
WALK_NESTED_ENUM(
OmpReductionClause, ReductionModifier) // OMP reduction-modifier
WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2289,7 +2289,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
bool OmpStructureChecker::CheckReductionOperators(
const parser::OmpClause::Reduction &x) {

const auto &definedOp{std::get<0>(x.v.t)};
const auto &definedOp{std::get<parser::OmpReductionOperator>(x.v.t)};
bool ok = false;
common::visit(
common::visitors{
Expand Down
50 changes: 50 additions & 0 deletions flang/test/Fir/cuf-invalid.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// RUN: fir-opt -split-input-file -verify-diagnostics %s

func.func @_QPsub1() {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFsub1Ea"}
%1 = fir.alloca i32
%pinned = fir.alloca i1
%4:2 = hlfir.declare %0 {cuda_attr = #fir.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%11 = fir.convert %4#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
%s = fir.load %1 : !fir.ref<i32>
// expected-error@+1{{'fir.cuda_allocate' op pinned and stream cannot appears at the same time}}
%13 = fir.cuda_allocate %11 : !fir.ref<!fir.box<none>> stream(%s : i32) pinned(%pinned : !fir.ref<i1>) {cuda_attr = #fir.cuda<device>} -> i32
return
}

// -----

func.func @_QPsub1() {
%1 = fir.alloca i32
// expected-error@+1{{'fir.cuda_allocate' op expect box to be a reference to/or a class or box type value}}
%2 = fir.cuda_allocate %1 : !fir.ref<i32> {cuda_attr = #fir.cuda<device>} -> i32
return
}

// -----

func.func @_QPsub1() {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFsub1Ea"}
%4:2 = hlfir.declare %0 {cuda_attr = #fir.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%c100 = arith.constant 100 : index
%7 = fir.alloca !fir.char<1,100> {bindc_name = "msg", uniq_name = "_QFsub1Emsg"}
%8:2 = hlfir.declare %7 typeparams %c100 {uniq_name = "_QFsub1Emsg"} : (!fir.ref<!fir.char<1,100>>, index) -> (!fir.ref<!fir.char<1,100>>, !fir.ref<!fir.char<1,100>>)
%9 = fir.embox %8#1 : (!fir.ref<!fir.char<1,100>>) -> !fir.box<!fir.char<1,100>>
%11 = fir.convert %4#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
%16 = fir.convert %9 : (!fir.box<!fir.char<1,100>>) -> !fir.box<none>
// expected-error@+1{{'fir.cuda_allocate' op expect stat attribute when errmsg is provided}}
%13 = fir.cuda_allocate %11 : !fir.ref<!fir.box<none>> errmsg(%16 : !fir.box<none>) {cuda_attr = #fir.cuda<device>} -> i32
return
}

// -----

func.func @_QPsub1() {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFsub1Ea"}
%4:2 = hlfir.declare %0 {cuda_attr = #fir.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%1 = fir.alloca i32
%11 = fir.convert %4#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
// expected-error@+1{{'fir.cuda_allocate' op expect errmsg to be a reference to/or a box type value}}
%13 = fir.cuda_allocate %11 : !fir.ref<!fir.box<none>> errmsg(%1 : !fir.ref<i32>) {cuda_attr = #fir.cuda<device>, hasStat} -> i32
return
}
70 changes: 70 additions & 0 deletions flang/test/Fir/cuf.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// RUN: fir-opt --split-input-file %s | fir-opt --split-input-file | FileCheck %s

// Simple round trip test of operations.

func.func @_QPsub1() {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFsub1Ea"}
%4:2 = hlfir.declare %0 {cuda_attr = #fir.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%11 = fir.convert %4#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
%13 = fir.cuda_allocate %11 : !fir.ref<!fir.box<none>> {cuda_attr = #fir.cuda<device>} -> i32
return
}

// CHECK: fir.cuda_allocate %{{.*}} : !fir.ref<!fir.box<none>> {cuda_attr = #fir.cuda<device>} -> i32

// -----

func.func @_QPsub1() {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFsub1Ea"}
%1 = fir.alloca i32
%4:2 = hlfir.declare %0 {cuda_attr = #fir.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%11 = fir.convert %4#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
%s = fir.load %1 : !fir.ref<i32>
%13 = fir.cuda_allocate %11 : !fir.ref<!fir.box<none>> stream(%s : i32) {cuda_attr = #fir.cuda<device>} -> i32
return
}

// CHECK: fir.cuda_allocate %{{.*}} : !fir.ref<!fir.box<none>> stream(%{{.*}} : i32) {cuda_attr = #fir.cuda<device>} -> i32

// -----

func.func @_QPsub1() {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFsub1Ea"}
%1 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "b", uniq_name = "_QFsub1Eb"}
%4:2 = hlfir.declare %0 {cuda_attr = #fir.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%5:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%11 = fir.convert %4#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
%12 = fir.convert %5#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
%13 = fir.cuda_allocate %11 : !fir.ref<!fir.box<none>> source(%12 : !fir.ref<!fir.box<none>>) {cuda_attr = #fir.cuda<device>} -> i32
return
}

// CHECK: fir.cuda_allocate %{{.*}} : !fir.ref<!fir.box<none>> source(%{{.*}} : !fir.ref<!fir.box<none>>) {cuda_attr = #fir.cuda<device>} -> i32

// -----

func.func @_QPsub1() {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFsub1Ea"}
%pinned = fir.alloca i1
%4:2 = hlfir.declare %0 {cuda_attr = #fir.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%11 = fir.convert %4#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
%13 = fir.cuda_allocate %11 : !fir.ref<!fir.box<none>> pinned(%pinned : !fir.ref<i1>) {cuda_attr = #fir.cuda<device>} -> i32
return
}

// CHECK: fir.cuda_allocate %{{.*}} : !fir.ref<!fir.box<none>> pinned(%{{.*}} : !fir.ref<i1>) {cuda_attr = #fir.cuda<device>} -> i32

// -----

func.func @_QPsub1() {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFsub1Ea"}
%4:2 = hlfir.declare %0 {cuda_attr = #fir.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
%c100 = arith.constant 100 : index
%7 = fir.alloca !fir.char<1,100> {bindc_name = "msg", uniq_name = "_QFsub1Emsg"}
%8:2 = hlfir.declare %7 typeparams %c100 {uniq_name = "_QFsub1Emsg"} : (!fir.ref<!fir.char<1,100>>, index) -> (!fir.ref<!fir.char<1,100>>, !fir.ref<!fir.char<1,100>>)
%9 = fir.embox %8#1 : (!fir.ref<!fir.char<1,100>>) -> !fir.box<!fir.char<1,100>>
%11 = fir.convert %4#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
%16 = fir.convert %9 : (!fir.box<!fir.char<1,100>>) -> !fir.box<none>
%13 = fir.cuda_allocate %11 : !fir.ref<!fir.box<none>> errmsg(%16 : !fir.box<none>) {cuda_attr = #fir.cuda<device>, hasStat} -> i32
return
}
13 changes: 13 additions & 0 deletions flang/test/Lower/OpenMP/Todo/reduction-modifiers.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s

! CHECK: not yet implemented: Reduction modifiers are not supported

subroutine foo()
integer :: i, j
j = 0
!$omp do reduction (inscan, *: j)
do i = 1, 10
j = j + 1
end do
end subroutine
20 changes: 20 additions & 0 deletions flang/test/Parser/OpenMP/reduction-modifier.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck --ignore-case %s
! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s

subroutine foo()
integer :: i, j
j = 0
! CHECK: !$OMP DO REDUCTION(TASK,*:j)
! PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
! PARSE-TREE: | | | OmpBeginLoopDirective
! PARSE-TREE: | | | | OmpLoopDirective -> llvm::omp::Directive = do
! PARSE-TREE: | | | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
! PARSE-TREE: | | | | | ReductionModifier = Task
! PARSE-TREE: | | | | | OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Multiply
! PARSE-TREE: | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j
!$omp do reduction (task, *: j)
do i = 1, 10
j = j + 1
end do
!$omp end do
end
18 changes: 18 additions & 0 deletions libc/hdr/types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,21 @@ add_proxy_header_library(
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.struct_timespec
)

add_proxy_header_library(
fenv_t
HDRS
fenv_t.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.fenv_t
libc.incude.fenv
)

add_proxy_header_library(
fexcept_t
HDRS
fexcept_t.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.fexcept_t
libc.incude.fenv
)
22 changes: 22 additions & 0 deletions libc/hdr/types/fenv_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Definition of macros from fenv_t.h --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_HDR_FENV_T_H
#define LLVM_LIBC_HDR_FENV_T_H

#ifdef LIBC_FULL_BUILD

#include "include/llvm-libc-types/fenv_t.h"

#else // Overlay mode

#include <fenv.h>

#endif // LLVM_LIBC_FULL_BUILD

#endif // LLVM_LIBC_HDR_FENV_T_H
22 changes: 22 additions & 0 deletions libc/hdr/types/fexcept_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Definition of macros from fexcept_t.h -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_HDR_FEXCEPT_T_H
#define LLVM_LIBC_HDR_FEXCEPT_T_H

#ifdef LIBC_FULL_BUILD

#include "include/llvm-libc-types/fexcept_t.h"

#else // Overlay mode

#include <fenv.h>

#endif // LLVM_LIBC_FULL_BUILD

#endif // LLVM_LIBC_HDR_FENV_T_H
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ add_header_library(
HDRS
FEnvImpl.h
DEPENDS
libc.include.fenv
libc.hdr.types.fenv_t
libc.hdr.fenv_macros
libc.hdr.math_macros
libc.src.__support.macros.attributes
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/aarch64/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
#endif

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

#include "hdr/fenv_macros.h"
#include "hdr/types/fenv_t.h"
#include "src/__support/FPUtil/FPBits.h"

namespace LIBC_NAMESPACE {
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
#endif

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

#include "hdr/fenv_macros.h"
#include "hdr/types/fenv_t.h"
#include "src/__support/FPUtil/FPBits.h"

namespace LIBC_NAMESPACE {
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/arm/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ARM_FENVIMPL_H

#include "hdr/fenv_macros.h"
#include "hdr/types/fenv_t.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/macros/attributes.h" // For LIBC_INLINE
#include <fenv.h>
#include <stdint.h>

namespace LIBC_NAMESPACE {
Expand Down
1 change: 1 addition & 0 deletions libc/src/__support/FPUtil/riscv/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_RISCV_FENVIMPL_H

#include "hdr/fenv_macros.h"
#include "hdr/types/fenv_t.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/macros/attributes.h" // For LIBC_INLINE_ASM
#include "src/__support/macros/config.h" // For LIBC_INLINE
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/x86_64/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
#error "Invalid include"
#endif

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

#include "hdr/types/fenv_t.h"
#include "src/__support/macros/sanitizer.h"

namespace LIBC_NAMESPACE {
Expand Down
7 changes: 6 additions & 1 deletion libc/src/fenv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ add_entrypoint_object(
HDRS
fegetround.h
DEPENDS
libc.include.fenv
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand Down Expand Up @@ -71,6 +70,7 @@ add_entrypoint_object(
fegetenv.h
DEPENDS
libc.hdr.fenv_macros
libc.hdr.types.fenv_t
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -84,6 +84,7 @@ add_entrypoint_object(
fesetenv.h
DEPENDS
libc.hdr.fenv_macros
libc.hdr.types.fenv_t
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -97,6 +98,7 @@ add_entrypoint_object(
fegetexceptflag.h
DEPENDS
libc.hdr.fenv_macros
libc.hdr.types.fexcept_t
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -123,6 +125,7 @@ add_entrypoint_object(
fesetexceptflag.h
DEPENDS
libc.hdr.fenv_macros
libc.hdr.types.fexcept_t
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -136,6 +139,7 @@ add_entrypoint_object(
feholdexcept.h
DEPENDS
libc.hdr.fenv_macros
libc.hdr.types.fenv_t
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -149,6 +153,7 @@ add_entrypoint_object(
feupdateenv.h
DEPENDS
libc.hdr.fenv_macros
libc.hdr.types.fenv_t
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand Down
2 changes: 1 addition & 1 deletion libc/src/fenv/fegetenv.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_FENV_FEGETENV_H
#define LLVM_LIBC_SRC_FENV_FEGETENV_H

#include <fenv.h>
#include "hdr/types/fenv_t.h"

namespace LIBC_NAMESPACE {

Expand Down
3 changes: 1 addition & 2 deletions libc/src/fenv/fegetexceptflag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
//===----------------------------------------------------------------------===//

#include "src/fenv/fegetexceptflag.h"
#include "hdr/types/fexcept_t.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/common.h"

#include <fenv.h>

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, fegetexceptflag, (fexcept_t * flagp, int excepts)) {
Expand Down
2 changes: 1 addition & 1 deletion libc/src/fenv/feholdexcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//

#include "src/fenv/feholdexcept.h"
#include "hdr/types/fenv_t.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/common.h"
#include <fenv.h>

namespace LIBC_NAMESPACE {

Expand Down
2 changes: 1 addition & 1 deletion libc/src/fenv/feholdexcept.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_FENV_FEHOLDEXCEPT_H
#define LLVM_LIBC_SRC_FENV_FEHOLDEXCEPT_H

#include <fenv.h>
#include "hdr/types/fenv_t.h"

namespace LIBC_NAMESPACE {

Expand Down
2 changes: 1 addition & 1 deletion libc/src/fenv/fesetenv.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_FENV_FESETENV_H
#define LLVM_LIBC_SRC_FENV_FESETENV_H

#include <fenv.h>
#include "hdr/types/fenv_t.h"

namespace LIBC_NAMESPACE {

Expand Down
2 changes: 1 addition & 1 deletion libc/src/fenv/fesetexceptflag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//

#include "src/fenv/fesetexceptflag.h"
#include "hdr/types/fexcept_t.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/common.h"
#include <fenv.h>

namespace LIBC_NAMESPACE {

Expand Down
2 changes: 1 addition & 1 deletion libc/src/fenv/feupdateenv.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_FENV_FEUPDATEENV_H
#define LLVM_LIBC_SRC_FENV_FEUPDATEENV_H

#include <fenv.h>
#include "hdr/types/fenv_t.h"

namespace LIBC_NAMESPACE {

Expand Down
1 change: 1 addition & 0 deletions libc/test/UnitTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ add_unittest_framework_library(
LibcTest
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.fenv_impl
libc.hdr.types.fenv_t
)

add_unittest_framework_library(
Expand Down
Loading