Skip to content

Commit f9987e0

Browse files
committed
rebase
Created using spr 1.3.8-beta.1
2 parents 74ce4fe + d61b21f commit f9987e0

File tree

89 files changed

+2275
-554
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+2275
-554
lines changed

clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H
1515
#define LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H
1616

17+
#include "clang/AST/ASTTypeTraits.h"
1718
#include "clang/AST/Decl.h"
1819
#include "clang/AST/Expr.h"
1920
#include "clang/AST/Stmt.h"
@@ -139,6 +140,12 @@ class UnsafeBufferUsageHandler {
139140
FixItList &&Fixes, const Decl *D,
140141
const FixitStrategy &VarTargetTypes) = 0;
141142

143+
// Invoked when an array subscript operator[] is used on a
144+
// std::unique_ptr<T[]>.
145+
virtual void handleUnsafeUniquePtrArrayAccess(const DynTypedNode &Node,
146+
bool IsRelatedToDecl,
147+
ASTContext &Ctx) = 0;
148+
142149
#ifndef NDEBUG
143150
public:
144151
bool areDebugNotesRequested() {

clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ WARNING_GADGET(PointerArithmetic)
3838
WARNING_GADGET(UnsafeBufferUsageAttr)
3939
WARNING_GADGET(UnsafeBufferUsageCtorAttr)
4040
WARNING_GADGET(DataInvocation)
41+
WARNING_GADGET(UniquePtrArrayAccess)
4142
WARNING_OPTIONAL_GADGET(UnsafeLibcFunctionCall)
4243
WARNING_OPTIONAL_GADGET(SpanTwoParamConstructor) // Uses of `std::span(arg0, arg1)`
4344
FIXABLE_GADGET(ULCArraySubscript) // `DRE[any]` in an Unspecified Lvalue Context

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1750,7 +1750,8 @@ def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">;
17501750
// Warnings and fixes to support the "safe buffers" programming model.
17511751
def UnsafeBufferUsageInContainer : DiagGroup<"unsafe-buffer-usage-in-container">;
17521752
def UnsafeBufferUsageInLibcCall : DiagGroup<"unsafe-buffer-usage-in-libc-call">;
1753-
def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInContainer, UnsafeBufferUsageInLibcCall]>;
1753+
def UnsafeBufferUsageInUniquePtrArrayAccess : DiagGroup<"unsafe-buffer-usage-in-unique-ptr-array-access">;
1754+
def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInContainer, UnsafeBufferUsageInLibcCall, UnsafeBufferUsageInUniquePtrArrayAccess]>;
17541755

17551756
// Warnings and notes InstallAPI verification.
17561757
def InstallAPIViolation : DiagGroup<"installapi-violation">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13295,6 +13295,8 @@ def note_safe_buffer_usage_suggestions_disabled : Note<
1329513295
def warn_unsafe_buffer_usage_in_container : Warning<
1329613296
"the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information">,
1329713297
InGroup<UnsafeBufferUsageInContainer>, DefaultIgnore;
13298+
def warn_unsafe_buffer_usage_unique_ptr_array_access : Warning<"direct access using operator[] on std::unique_ptr<T[]> is unsafe due to lack of bounds checking">,
13299+
InGroup<UnsafeBufferUsageInUniquePtrArrayAccess>, DefaultIgnore;
1329813300
#ifndef NDEBUG
1329913301
// Not a user-facing diagnostic. Useful for debugging false negatives in
1330013302
// -fsafe-buffer-usage-suggestions (i.e. lack of -Wunsafe-buffer-usage fixits).

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,51 @@ def CIR_VisibilityAttr : CIR_EnumAttr<CIR_VisibilityKind, "visibility"> {
769769
}];
770770
}
771771

772+
//===----------------------------------------------------------------------===//
773+
// GloblCtorAttr
774+
//===----------------------------------------------------------------------===//
775+
776+
class CIR_GlobalCtorDtor<string name, string attrMnemonic>
777+
: CIR_Attr<"Global" # name, "global_" # attrMnemonic> {
778+
let parameters = (ins "mlir::StringAttr":$name, "int":$priority);
779+
780+
let skipDefaultBuilders = 1;
781+
let builders = [
782+
AttrBuilder<(ins
783+
"llvm::StringRef":$name,
784+
CArg<"int", "65535">:$priority), [{
785+
return $_get($_ctxt, mlir::StringAttr::get($_ctxt, name), priority);
786+
}]>,
787+
AttrBuilderWithInferredContext<(ins
788+
"mlir::StringAttr":$name,
789+
CArg<"int", "65535">:$priority), [{
790+
return $_get(name.getContext(), name, priority);
791+
}]>
792+
];
793+
794+
let assemblyFormat = [{
795+
`<` $name `,` $priority `>`
796+
}];
797+
798+
let extraClassDeclaration = [{
799+
bool isDefaultPriority() const {
800+
return getPriority() == getDefaultPriority();
801+
};
802+
803+
static int getDefaultPriority() {
804+
return 65535;
805+
}
806+
}];
807+
}
808+
809+
def CIR_GlobalCtorAttr : CIR_GlobalCtorDtor<"Ctor", "ctor"> {
810+
let summary = "Marks a function as a global constructor";
811+
let description = [{
812+
Marks the function as a global constructor in the module's constructor list.
813+
It will be executed before main() is called.
814+
}];
815+
}
816+
772817
//===----------------------------------------------------------------------===//
773818
// BitfieldInfoAttr
774819
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "mlir/Dialect/DLTI/DLTI.h"
1616
#include "mlir/IR/BuiltinOps.h"
17+
#include "clang/CIR/Dialect/IR/CIRTypes.h"
1718

1819
namespace cir {
1920

@@ -81,6 +82,18 @@ class CIRDataLayout {
8182
}
8283

8384
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const;
85+
86+
llvm::TypeSize getPointerTypeSizeInBits(mlir::Type ty) const {
87+
assert(mlir::isa<cir::PointerType>(ty) &&
88+
"This should only be called with a pointer type");
89+
return layout.getTypeSizeInBits(ty);
90+
}
91+
92+
mlir::Type getIntPtrType(mlir::Type ty) const {
93+
assert(mlir::isa<cir::PointerType>(ty) && "Expected pointer type");
94+
return cir::IntType::get(ty.getContext(), getPointerTypeSizeInBits(ty),
95+
false);
96+
}
8497
};
8598

8699
} // namespace cir

clang/include/clang/CIR/Dialect/IR/CIRDialect.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def CIR_Dialect : Dialect {
4242
static llvm::StringRef getNoThrowAttrName() { return "nothrow"; }
4343
static llvm::StringRef getSideEffectAttrName() { return "side_effect"; }
4444
static llvm::StringRef getModuleLevelAsmAttrName() { return "cir.module_asm"; }
45+
static llvm::StringRef getGlobalCtorsAttrName() { return "cir.global_ctors"; }
4546

4647
void registerAttributes();
4748
void registerTypes();

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ struct MissingFeatures {
3939
static bool opGlobalUsedOrCompilerUsed() { return false; }
4040
static bool opGlobalAnnotations() { return false; }
4141
static bool opGlobalDtorLowering() { return false; }
42-
static bool opGlobalCtorAttr() { return false; }
4342
static bool opGlobalCtorPriority() { return false; }
4443
static bool opGlobalCtorList() { return false; }
4544
static bool setDSOLocal() { return false; }

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clang/AST/Attr.h"
1414
#include "clang/AST/Decl.h"
1515
#include "clang/AST/DeclCXX.h"
16+
#include "clang/AST/DeclTemplate.h"
1617
#include "clang/AST/DynamicRecursiveASTVisitor.h"
1718
#include "clang/AST/Expr.h"
1819
#include "clang/AST/FormatString.h"
@@ -1318,6 +1319,97 @@ static bool isSupportedVariable(const DeclRefExpr &Node) {
13181319
return D != nullptr && isa<VarDecl>(D);
13191320
}
13201321

1322+
// Returns true for RecordDecl of type std::unique_ptr<T[]>
1323+
static bool isUniquePtrArray(const CXXRecordDecl *RecordDecl) {
1324+
if (!RecordDecl || !RecordDecl->isInStdNamespace() ||
1325+
RecordDecl->getNameAsString() != "unique_ptr")
1326+
return false;
1327+
1328+
const ClassTemplateSpecializationDecl *class_template_specialization_decl =
1329+
dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
1330+
if (!class_template_specialization_decl)
1331+
return false;
1332+
1333+
const TemplateArgumentList &template_args =
1334+
class_template_specialization_decl->getTemplateArgs();
1335+
if (template_args.size() == 0)
1336+
return false;
1337+
1338+
const TemplateArgument &first_arg = template_args[0];
1339+
if (first_arg.getKind() != TemplateArgument::Type)
1340+
return false;
1341+
1342+
QualType referred_type = first_arg.getAsType();
1343+
return referred_type->isArrayType();
1344+
}
1345+
1346+
class UniquePtrArrayAccessGadget : public WarningGadget {
1347+
private:
1348+
static constexpr const char *const AccessorTag = "unique_ptr_array_access";
1349+
const CXXOperatorCallExpr *AccessorExpr;
1350+
1351+
public:
1352+
UniquePtrArrayAccessGadget(const MatchResult &Result)
1353+
: WarningGadget(Kind::UniquePtrArrayAccess),
1354+
AccessorExpr(Result.getNodeAs<CXXOperatorCallExpr>(AccessorTag)) {
1355+
assert(AccessorExpr &&
1356+
"UniquePtrArrayAccessGadget requires a matched CXXOperatorCallExpr");
1357+
}
1358+
1359+
static bool classof(const Gadget *G) {
1360+
return G->getKind() == Kind::UniquePtrArrayAccess;
1361+
}
1362+
1363+
static bool matches(const Stmt *S, const ASTContext &Ctx,
1364+
MatchResult &Result) {
1365+
1366+
const CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(S);
1367+
if (!OpCall || OpCall->getOperator() != OO_Subscript)
1368+
return false;
1369+
1370+
const Expr *Callee = OpCall->getCallee()->IgnoreParenImpCasts();
1371+
if (!Callee)
1372+
return false;
1373+
1374+
const CXXMethodDecl *Method =
1375+
dyn_cast_or_null<CXXMethodDecl>(OpCall->getDirectCallee());
1376+
if (!Method)
1377+
return false;
1378+
1379+
if (Method->getOverloadedOperator() != OO_Subscript)
1380+
return false;
1381+
1382+
const CXXRecordDecl *RecordDecl = Method->getParent();
1383+
if (!isUniquePtrArray(RecordDecl))
1384+
return false;
1385+
1386+
const Expr *IndexExpr = OpCall->getArg(1);
1387+
clang::Expr::EvalResult Eval;
1388+
1389+
// Allow [0]
1390+
if (IndexExpr->EvaluateAsInt(Eval, Ctx) && Eval.Val.getInt().isZero())
1391+
return false;
1392+
1393+
Result.addNode(AccessorTag, DynTypedNode::create(*OpCall));
1394+
return true;
1395+
}
1396+
void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
1397+
bool IsRelatedToDecl,
1398+
ASTContext &Ctx) const override {
1399+
Handler.handleUnsafeUniquePtrArrayAccess(
1400+
DynTypedNode::create(*AccessorExpr), IsRelatedToDecl, Ctx);
1401+
}
1402+
1403+
SourceLocation getSourceLoc() const override {
1404+
if (AccessorExpr)
1405+
return AccessorExpr->getOperatorLoc();
1406+
return SourceLocation();
1407+
}
1408+
1409+
DeclUseList getClaimedVarUseSites() const override { return {}; }
1410+
SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
1411+
};
1412+
13211413
using FixableGadgetList = std::vector<std::unique_ptr<FixableGadget>>;
13221414
using WarningGadgetList = std::vector<std::unique_ptr<WarningGadget>>;
13231415

@@ -2632,10 +2724,13 @@ std::set<const Expr *> clang::findUnsafePointers(const FunctionDecl *FD) {
26322724
const VariableGroupsManager &, FixItList &&,
26332725
const Decl *,
26342726
const FixitStrategy &) override {}
2635-
bool isSafeBufferOptOut(const SourceLocation &) const override {
2727+
void handleUnsafeUniquePtrArrayAccess(const DynTypedNode &Node,
2728+
bool IsRelatedToDecl,
2729+
ASTContext &Ctx) override {}
2730+
bool ignoreUnsafeBufferInContainer(const SourceLocation &) const override {
26362731
return false;
26372732
}
2638-
bool ignoreUnsafeBufferInContainer(const SourceLocation &) const override {
2733+
bool isSafeBufferOptOut(const SourceLocation &) const override {
26392734
return false;
26402735
}
26412736
bool ignoreUnsafeBufferInLibcCall(const SourceLocation &) const override {

clang/lib/Basic/Diagnostic.cpp

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,6 @@ class WarningsSpecialCaseList : public llvm::SpecialCaseList {
517517
const SourceManager &SM) const;
518518

519519
private:
520-
// Find the longest glob pattern that matches FilePath amongst
521-
// CategoriesToMatchers, return true iff the match exists and belongs to a
522-
// positive category.
523-
bool globsMatches(const llvm::StringMap<Matcher> &CategoriesToMatchers,
524-
StringRef FilePath) const;
525-
526520
llvm::DenseMap<diag::kind, const Section *> DiagToSection;
527521
};
528522
} // namespace
@@ -584,43 +578,24 @@ void DiagnosticsEngine::setDiagSuppressionMapping(llvm::MemoryBuffer &Input) {
584578
bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId,
585579
SourceLocation DiagLoc,
586580
const SourceManager &SM) const {
581+
PresumedLoc PLoc = SM.getPresumedLoc(DiagLoc);
582+
if (!PLoc.isValid())
583+
return false;
587584
const Section *DiagSection = DiagToSection.lookup(DiagId);
588585
if (!DiagSection)
589586
return false;
590-
const SectionEntries &EntityTypeToCategories = DiagSection->Entries;
591-
auto SrcEntriesIt = EntityTypeToCategories.find("src");
592-
if (SrcEntriesIt == EntityTypeToCategories.end())
587+
588+
StringRef F = llvm::sys::path::remove_leading_dotslash(PLoc.getFilename());
589+
590+
StringRef LongestSup = DiagSection->getLongestMatch("src", F, "");
591+
if (LongestSup.empty())
593592
return false;
594-
const llvm::StringMap<llvm::SpecialCaseList::Matcher> &CategoriesToMatchers =
595-
SrcEntriesIt->getValue();
596-
// We also use presumed locations here to improve reproducibility for
597-
// preprocessed inputs.
598-
if (PresumedLoc PLoc = SM.getPresumedLoc(DiagLoc); PLoc.isValid())
599-
return globsMatches(
600-
CategoriesToMatchers,
601-
llvm::sys::path::remove_leading_dotslash(PLoc.getFilename()));
602-
return false;
603-
}
604593

605-
bool WarningsSpecialCaseList::globsMatches(
606-
const llvm::StringMap<Matcher> &CategoriesToMatchers,
607-
StringRef FilePath) const {
608-
StringRef LongestMatch;
609-
bool LongestIsPositive = false;
610-
for (const auto &Entry : CategoriesToMatchers) {
611-
StringRef Category = Entry.getKey();
612-
const llvm::SpecialCaseList::Matcher &Matcher = Entry.getValue();
613-
bool IsPositive = Category != "emit";
614-
for (const auto &Glob : Matcher.Globs) {
615-
if (Glob->Name.size() < LongestMatch.size())
616-
continue;
617-
if (!Glob->Pattern.match(FilePath))
618-
continue;
619-
LongestMatch = Glob->Name;
620-
LongestIsPositive = IsPositive;
621-
}
622-
}
623-
return LongestIsPositive;
594+
StringRef LongestEmit = DiagSection->getLongestMatch("src", F, "emit");
595+
if (LongestEmit.empty())
596+
return true;
597+
598+
return LongestSup.size() > LongestEmit.size();
624599
}
625600

626601
bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind DiagId,

0 commit comments

Comments
 (0)