Skip to content

Commit

Permalink
merge main into amd-staging
Browse files Browse the repository at this point in the history
Change-Id: If3f3caed946212372255a9a0d02444b9685869ff
  • Loading branch information
ronlieb committed Nov 15, 2024
2 parents 5e5afd1 + 98daf22 commit 946a540
Show file tree
Hide file tree
Showing 222 changed files with 4,963 additions and 2,194 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/libcxx-build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ jobs:
matrix:
include:
- config: generic-cxx03
os: macos-latest
os: macos-15
- config: generic-cxx23
os: macos-latest
os: macos-15
- config: generic-modules
os: macos-latest
os: macos-15
- config: apple-configuration
os: macos-latest
os: macos-15
- config: apple-system
os: macos-13
- config: apple-system-hardened
Expand Down
127 changes: 45 additions & 82 deletions clang/lib/Analysis/UnsafeBufferUsage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,6 @@ class MatchDescendantVisitor
return VisitorBase::TraverseCXXTypeidExpr(Node);
}

bool TraverseCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
if (!TraverseStmt(Node->getExpr()))
return false;
return VisitorBase::TraverseCXXDefaultInitExpr(Node);
}

bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) {
if (!Node)
return true;
Expand Down Expand Up @@ -1998,18 +1992,14 @@ class DerefSimplePtrArithFixableGadget : public FixableGadget {
};

/// Scan the function and return a list of gadgets found with provided kits.
static void findGadgets(const Stmt *S, ASTContext &Ctx,
const UnsafeBufferUsageHandler &Handler,
bool EmitSuggestions, FixableGadgetList &FixableGadgets,
WarningGadgetList &WarningGadgets,
DeclUseTracker &Tracker) {
static std::tuple<FixableGadgetList, WarningGadgetList, DeclUseTracker>
findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
bool EmitSuggestions) {

struct GadgetFinderCallback : MatchFinder::MatchCallback {
GadgetFinderCallback(FixableGadgetList &FixableGadgets,
WarningGadgetList &WarningGadgets,
DeclUseTracker &Tracker)
: FixableGadgets(FixableGadgets), WarningGadgets(WarningGadgets),
Tracker(Tracker) {}
FixableGadgetList FixableGadgets;
WarningGadgetList WarningGadgets;
DeclUseTracker Tracker;

void run(const MatchFinder::MatchResult &Result) override {
// In debug mode, assert that we've found exactly one gadget.
Expand Down Expand Up @@ -2050,14 +2040,10 @@ static void findGadgets(const Stmt *S, ASTContext &Ctx,
assert(numFound >= 1 && "Gadgets not found in match result!");
assert(numFound <= 1 && "Conflicting bind tags in gadgets!");
}

FixableGadgetList &FixableGadgets;
WarningGadgetList &WarningGadgets;
DeclUseTracker &Tracker;
};

MatchFinder M;
GadgetFinderCallback CB{FixableGadgets, WarningGadgets, Tracker};
GadgetFinderCallback CB;

// clang-format off
M.addMatcher(
Expand Down Expand Up @@ -2102,7 +2088,9 @@ static void findGadgets(const Stmt *S, ASTContext &Ctx,
// clang-format on
}

M.match(*S, Ctx);
M.match(*D->getBody(), D->getASTContext());
return {std::move(CB.FixableGadgets), std::move(CB.WarningGadgets),
std::move(CB.Tracker)};
}

// Compares AST nodes by source locations.
Expand Down Expand Up @@ -3646,9 +3634,39 @@ class VariableGroupsManagerImpl : public VariableGroupsManager {
}
};

void applyGadgets(const Decl *D, FixableGadgetList FixableGadgets,
WarningGadgetList WarningGadgets, DeclUseTracker Tracker,
UnsafeBufferUsageHandler &Handler, bool EmitSuggestions) {
void clang::checkUnsafeBufferUsage(const Decl *D,
UnsafeBufferUsageHandler &Handler,
bool EmitSuggestions) {
#ifndef NDEBUG
Handler.clearDebugNotes();
#endif

assert(D && D->getBody());
// We do not want to visit a Lambda expression defined inside a method
// independently. Instead, it should be visited along with the outer method.
// FIXME: do we want to do the same thing for `BlockDecl`s?
if (const auto *fd = dyn_cast<CXXMethodDecl>(D)) {
if (fd->getParent()->isLambda() && fd->getParent()->isLocalClass())
return;
}

// Do not emit fixit suggestions for functions declared in an
// extern "C" block.
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
for (FunctionDecl *FReDecl : FD->redecls()) {
if (FReDecl->isExternC()) {
EmitSuggestions = false;
break;
}
}
}

WarningGadgetSets UnsafeOps;
FixableGadgetSets FixablesForAllVars;

auto [FixableGadgets, WarningGadgets, Tracker] =
findGadgets(D, Handler, EmitSuggestions);

if (!EmitSuggestions) {
// Our job is very easy without suggestions. Just warn about
// every problematic operation and consider it done. No need to deal
Expand Down Expand Up @@ -3692,10 +3710,8 @@ void applyGadgets(const Decl *D, FixableGadgetList FixableGadgets,
if (WarningGadgets.empty())
return;

WarningGadgetSets UnsafeOps =
groupWarningGadgetsByVar(std::move(WarningGadgets));
FixableGadgetSets FixablesForAllVars =
groupFixablesByVar(std::move(FixableGadgets));
UnsafeOps = groupWarningGadgetsByVar(std::move(WarningGadgets));
FixablesForAllVars = groupFixablesByVar(std::move(FixableGadgets));

std::map<const VarDecl *, FixItList> FixItsForVariableGroup;

Expand Down Expand Up @@ -3916,56 +3932,3 @@ void applyGadgets(const Decl *D, FixableGadgetList FixableGadgets,
}
}
}

void clang::checkUnsafeBufferUsage(const Decl *D,
UnsafeBufferUsageHandler &Handler,
bool EmitSuggestions) {
#ifndef NDEBUG
Handler.clearDebugNotes();
#endif

assert(D);

SmallVector<Stmt *> Stmts;

if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// We do not want to visit a Lambda expression defined inside a method
// independently. Instead, it should be visited along with the outer method.
// FIXME: do we want to do the same thing for `BlockDecl`s?
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->getParent()->isLambda() && MD->getParent()->isLocalClass())
return;
}

for (FunctionDecl *FReDecl : FD->redecls()) {
if (FReDecl->isExternC()) {
// Do not emit fixit suggestions for functions declared in an
// extern "C" block.
EmitSuggestions = false;
break;
}
}

Stmts.push_back(FD->getBody());

if (const auto *ID = dyn_cast<CXXConstructorDecl>(D)) {
for (const CXXCtorInitializer *CI : ID->inits()) {
Stmts.push_back(CI->getInit());
}
}
} else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
Stmts.push_back(D->getBody());
}

assert(!Stmts.empty());

FixableGadgetList FixableGadgets;
WarningGadgetList WarningGadgets;
DeclUseTracker Tracker;
for (Stmt *S : Stmts) {
findGadgets(S, D->getASTContext(), Handler, EmitSuggestions, FixableGadgets,
WarningGadgets, Tracker);
}
applyGadgets(D, std::move(FixableGadgets), std::move(WarningGadgets),
std::move(Tracker), Handler, EmitSuggestions);
}
14 changes: 6 additions & 8 deletions clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2836,10 +2836,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() {
if (BlockObjectDispose)
return BlockObjectDispose;

llvm::Type *args[] = { Int8PtrTy, Int32Ty };
llvm::FunctionType *fty
= llvm::FunctionType::get(VoidTy, args, false);
BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose");
QualType args[] = {Context.VoidPtrTy, Context.IntTy};
BlockObjectDispose =
CreateRuntimeFunction(Context.VoidTy, args, "_Block_object_dispose");
configureBlocksRuntimeObject(
*this, cast<llvm::Constant>(BlockObjectDispose.getCallee()));
return BlockObjectDispose;
Expand All @@ -2849,10 +2848,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() {
if (BlockObjectAssign)
return BlockObjectAssign;

llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
llvm::FunctionType *fty
= llvm::FunctionType::get(VoidTy, args, false);
BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign");
QualType args[] = {Context.VoidPtrTy, Context.VoidPtrTy, Context.IntTy};
BlockObjectAssign =
CreateRuntimeFunction(Context.VoidTy, args, "_Block_object_assign");
configureBlocksRuntimeObject(
*this, cast<llvm::Constant>(BlockObjectAssign.getCallee()));
return BlockObjectAssign;
Expand Down
64 changes: 49 additions & 15 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4914,6 +4914,52 @@ GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {
return nullptr;
}

static void setWindowsItaniumDLLImport(CodeGenModule &CGM, bool Local,
llvm::Function *F, StringRef Name) {
// In Windows Itanium environments, try to mark runtime functions
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
// will link their standard library statically or dynamically. Marking
// functions imported when they are not imported can cause linker errors
// and warnings.
if (!Local && CGM.getTriple().isWindowsItaniumEnvironment() &&
!CGM.getCodeGenOpts().LTOVisibilityPublicStd) {
const FunctionDecl *FD = GetRuntimeFunctionDecl(CGM.getContext(), Name);
if (!FD || FD->hasAttr<DLLImportAttr>()) {
F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
}

llvm::FunctionCallee CodeGenModule::CreateRuntimeFunction(
QualType ReturnTy, ArrayRef<QualType> ArgTys, StringRef Name,
llvm::AttributeList ExtraAttrs, bool Local, bool AssumeConvergent) {
if (AssumeConvergent) {
ExtraAttrs =
ExtraAttrs.addFnAttribute(VMContext, llvm::Attribute::Convergent);
}

QualType FTy = Context.getFunctionType(ReturnTy, ArgTys,
FunctionProtoType::ExtProtoInfo());
const CGFunctionInfo &Info = getTypes().arrangeFreeFunctionType(
Context.getCanonicalType(FTy).castAs<FunctionProtoType>());
auto *ConvTy = getTypes().GetFunctionType(Info);
llvm::Constant *C = GetOrCreateLLVMFunction(
Name, ConvTy, GlobalDecl(), /*ForVTable=*/false,
/*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs);

if (auto *F = dyn_cast<llvm::Function>(C)) {
if (F->empty()) {
SetLLVMFunctionAttributes(GlobalDecl(), Info, F, /*IsThunk*/ false);
// FIXME: Set calling-conv properly in ExtProtoInfo
F->setCallingConv(getRuntimeCC());
setWindowsItaniumDLLImport(*this, Local, F, Name);
setDSOLocal(F);
}
}
return {ConvTy, C};
}

/// CreateRuntimeFunction - Create a new runtime function with the specified
/// type and name.
llvm::FunctionCallee
Expand All @@ -4933,24 +4979,12 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
if (auto *F = dyn_cast<llvm::Function>(C)) {
if (F->empty()) {
F->setCallingConv(getRuntimeCC());

// In Windows Itanium environments, try to mark runtime functions
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
// will link their standard library statically or dynamically. Marking
// functions imported when they are not imported can cause linker errors
// and warnings.
if (!Local && getTriple().isWindowsItaniumEnvironment() &&
!getCodeGenOpts().LTOVisibilityPublicStd) {
const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
if (!FD || FD->hasAttr<DLLImportAttr>()) {
F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
setWindowsItaniumDLLImport(*this, Local, F, Name);
setDSOLocal(F);
// FIXME: We should use CodeGenModule::SetLLVMFunctionAttributes() instead
// of trying to approximate the attributes using the LLVM function
// signature. This requires revising the API of CreateRuntimeFunction().
// signature. The other overload of CreateRuntimeFunction does this; it
// should be used for new code.
markRegisterParameterAttributes(F);
}
}
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1389,11 +1389,23 @@ class CodeGenModule : public CodeGenTypeCache {
/// Create or return a runtime function declaration with the specified type
/// and name. If \p AssumeConvergent is true, the call will have the
/// convergent attribute added.
///
/// For new code, please use the overload that takes a QualType; it sets
/// function attributes more accurately.
llvm::FunctionCallee
CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name,
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
bool Local = false, bool AssumeConvergent = false);

/// Create or return a runtime function declaration with the specified type
/// and name. If \p AssumeConvergent is true, the call will have the
/// convergent attribute added.
llvm::FunctionCallee
CreateRuntimeFunction(QualType ReturnTy, ArrayRef<QualType> ArgTys,
StringRef Name,
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
bool Local = false, bool AssumeConvergent = false);

/// Create a new runtime global variable with the specified type and name.
llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
return false;

case llvm::Triple::hexagon:
case llvm::Triple::msp430:
case llvm::Triple::ppcle:
case llvm::Triple::ppc64le:
case llvm::Triple::riscv32:
Expand Down
Loading

0 comments on commit 946a540

Please sign in to comment.