Skip to content

Commit be88cf9

Browse files
authored
[BoundsSafety] Bring full support for -fbounds-safety (#9707)
1 parent 8ff38c7 commit be88cf9

File tree

1,205 files changed

+225870
-13045
lines changed

Some content is hidden

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

1,205 files changed

+225870
-13045
lines changed

clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@ void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(
257257
SourceLocation Loc) {
258258
parseToLocation(Loc);
259259
}
260+
/*TO_UPSTREAM(BoundsSafety) ON*/
261+
void ExpandModularHeadersPPCallbacks::
262+
PragmaAbiPointerAttributesSet(SourceLocation Loc,
263+
ArrayRef<const IdentifierInfo *> Spec) {
264+
parseToLocation(Loc);
265+
}
266+
/*TO_UPSTREAM(BoundsSafety) OFF*/
260267
void ExpandModularHeadersPPCallbacks::MacroExpands(const Token &MacroNameTok,
261268
const MacroDefinition &,
262269
SourceRange Range,

clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ class ExpandModularHeadersPPCallbacks : public PPCallbacks {
9999
void PragmaWarningPop(SourceLocation Loc) override;
100100
void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
101101
void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
102+
/*TO_UPSTREAM(BoundsSafety) ON*/
103+
void PragmaAbiPointerAttributesSet(SourceLocation Loc,
104+
ArrayRef<const IdentifierInfo *>) override;
105+
/*TO_UPSTREAM(BoundsSafety) OFF*/
102106
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &,
103107
SourceRange Range, const MacroArgs *) override;
104108
void MacroDefined(const Token &MacroNameTok,

clang/include/clang-c/Index.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,17 @@ enum CXCursorKind {
16911691
*/
16921692
CXCursor_PackIndexingExpr = 156,
16931693

1694-
CXCursor_LastExpr = CXCursor_PackIndexingExpr,
1694+
/* TO_UPSTREAM(BoundsSafety) ON */
1695+
/**
1696+
* BoundsSafety '__builtin_unsafe_forge_bidi_indexable(addr, size)' or
1697+
* '__builtin_forge_single(addr)
1698+
*/
1699+
CXCursor_ForgePtrExpr = 198,
1700+
1701+
CXCursor_GetBoundExpr = 199,
1702+
1703+
CXCursor_LastExpr = CXCursor_GetBoundExpr,
1704+
/* TO_UPSTREAM(BoundsSafety) OFF */
16951705

16961706
/* Statements */
16971707
CXCursor_FirstStmt = 200,

clang/include/clang/AST/APValue.h

Lines changed: 185 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_CLANG_AST_APVALUE_H
1414
#define LLVM_CLANG_AST_APVALUE_H
1515

16+
#include "clang/AST/CharUnits.h"
1617
#include "clang/Basic/LLVM.h"
1718
#include "llvm/ADT/APFixedPoint.h"
1819
#include "llvm/ADT/APFloat.h"
@@ -29,7 +30,6 @@ template <typename T> class BasicReaderBase;
2930

3031
class AddrLabelExpr;
3132
class ASTContext;
32-
class CharUnits;
3333
class CXXRecordDecl;
3434
class Decl;
3535
class DiagnosticBuilder;
@@ -88,6 +88,59 @@ class DynamicAllocLValue {
8888

8989
static constexpr int NumLowBitsAvailable = 3;
9090
};
91+
92+
/* TO_UPSTREAM(BoundsSafety) ON*/
93+
/// Symbolic representation of a size forged pointer
94+
class ForgedPtrLValue {
95+
const ValueDecl *Base;
96+
97+
public:
98+
ForgedPtrLValue() : Base(nullptr) {}
99+
explicit ForgedPtrLValue(const ValueDecl *Base) : Base(Base) {}
100+
explicit operator bool() const { return Base; }
101+
102+
const ValueDecl *getBaseValueDecl() const { return Base; }
103+
104+
void *getOpaqueValue() { return const_cast<ValueDecl *>(Base); }
105+
static ForgedPtrLValue getFromOpaqueValue(void *Value) {
106+
ForgedPtrLValue V;
107+
V.Base = reinterpret_cast<ValueDecl *>(Value);
108+
return V;
109+
}
110+
};
111+
112+
/// This represents a pointer union that is either DynamicAllocLValue or
113+
/// ForgedPtrLValue.
114+
///
115+
/// This is a hack to be able to add ForgedPtrLValue as another pointer member
116+
/// to the pointer union of APValue::LValueBase because it already has the
117+
/// maximum number of members for the available low bits, i.e., 2.
118+
/// DynamicAllocLValue and ValueDecl* have 3 low bits available and thus we can
119+
/// use this one more remaining bit to encode ForgedPtrLValue.
120+
class DynamicAllocOrForgedPtrLValue
121+
: public llvm::PointerUnion<DynamicAllocLValue, ForgedPtrLValue> {
122+
123+
using BaseTy = llvm::PointerUnion<DynamicAllocLValue, ForgedPtrLValue>;
124+
125+
public:
126+
DynamicAllocOrForgedPtrLValue() = default;
127+
DynamicAllocOrForgedPtrLValue(DynamicAllocLValue LV) : BaseTy(LV) {}
128+
DynamicAllocOrForgedPtrLValue(ForgedPtrLValue LV) : BaseTy(LV) {}
129+
130+
explicit operator bool() const {
131+
if (is<DynamicAllocLValue>()) {
132+
return static_cast<bool>(get<DynamicAllocLValue>());
133+
}
134+
return static_cast<bool>(get<ForgedPtrLValue>());
135+
}
136+
137+
static DynamicAllocOrForgedPtrLValue getFromOpaqueValue(void *Value) {
138+
DynamicAllocOrForgedPtrLValue V;
139+
V.Val.setFromOpaqueValue(Value);
140+
return V;
141+
}
142+
};
143+
/* TO_UPSTREAM(BoundsSafety) OFF*/
91144
}
92145

93146
namespace llvm {
@@ -113,6 +166,28 @@ template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
113166
static constexpr int NumLowBitsAvailable =
114167
clang::DynamicAllocLValue::NumLowBitsAvailable;
115168
};
169+
170+
/* TO_UPSTREAM(BoundsSafety) ON*/
171+
template <> struct PointerLikeTypeTraits<clang::ForgedPtrLValue> {
172+
static void *getAsVoidPointer(clang::ForgedPtrLValue V) {
173+
return V.getOpaqueValue();
174+
}
175+
static clang::ForgedPtrLValue getFromVoidPointer(void *P) {
176+
return clang::ForgedPtrLValue::getFromOpaqueValue(P);
177+
}
178+
static constexpr int NumLowBitsAvailable = 3;
179+
};
180+
181+
template <> struct PointerLikeTypeTraits<clang::DynamicAllocOrForgedPtrLValue> {
182+
static void *getAsVoidPointer(clang::DynamicAllocOrForgedPtrLValue V) {
183+
return V.getOpaqueValue();
184+
}
185+
static clang::DynamicAllocOrForgedPtrLValue getFromVoidPointer(void *P) {
186+
return clang::DynamicAllocOrForgedPtrLValue::getFromOpaqueValue(P);
187+
}
188+
static constexpr int NumLowBitsAvailable = 2;
189+
};
190+
/* TO_UPSTREAM(BoundsSafety) OFF*/
116191
}
117192

118193
namespace clang {
@@ -145,28 +220,64 @@ class APValue {
145220

146221
class LValueBase {
147222
typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
148-
DynamicAllocLValue>
223+
DynamicAllocOrForgedPtrLValue>
149224
PtrTy;
150225

226+
template <class T>
227+
static constexpr bool IsDAOrForgedV =
228+
std::is_same<T, DynamicAllocLValue>::value ||
229+
std::is_same<T, ForgedPtrLValue>::value;
230+
231+
template <class T, class U = T>
232+
using EnableIfDAOrForged =
233+
typename std::enable_if<IsDAOrForgedV<T>, U>::type;
234+
235+
template <class T, class U = T>
236+
using EnableIfNotDANorForged =
237+
typename std::enable_if<!IsDAOrForgedV<T>, U>::type;
238+
151239
public:
152240
LValueBase() : Local{} {}
153241
LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
154242
LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
155243
static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
156244
static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
245+
static LValueBase getForgedPtr(ForgedPtrLValue LV, QualType Type);
157246

158247
void Profile(llvm::FoldingSetNodeID &ID) const;
159248

160-
template <class T>
161-
bool is() const { return Ptr.is<T>(); }
249+
template <class T> EnableIfNotDANorForged<T, bool> is() const {
250+
return Ptr.is<T>();
251+
}
162252

163-
template <class T>
164-
T get() const { return Ptr.get<T>(); }
253+
template <class T> EnableIfDAOrForged<T, bool> is() const {
254+
if (!Ptr.is<DynamicAllocOrForgedPtrLValue>())
255+
return false;
256+
return Ptr.get<DynamicAllocOrForgedPtrLValue>().is<T>();
257+
}
165258

166-
template <class T>
167-
T dyn_cast() const { return Ptr.dyn_cast<T>(); }
259+
template <class T> EnableIfNotDANorForged<T> get() const {
260+
return Ptr.get<T>();
261+
}
262+
263+
template <class T> EnableIfDAOrForged<T> get() const {
264+
assert(is<T>() && "Invalid accessor called");
265+
return Ptr.get<DynamicAllocOrForgedPtrLValue>().get<T>();
266+
}
267+
268+
template <class T> EnableIfNotDANorForged<T> dyn_cast() const {
269+
return Ptr.dyn_cast<T>();
270+
}
271+
272+
template <class T> EnableIfDAOrForged<T> dyn_cast() const {
273+
if (is<T>())
274+
return Ptr.get<DynamicAllocOrForgedPtrLValue>().dyn_cast<T>();
275+
return T();
276+
}
168277

169278
void *getOpaqueValue() const;
279+
// TO_UPSTREAM(BoundsSafety)
280+
const ValueDecl *getValueDecl() const;
170281

171282
bool isNull() const;
172283

@@ -176,6 +287,7 @@ class APValue {
176287
unsigned getVersion() const;
177288
QualType getTypeInfoType() const;
178289
QualType getDynamicAllocType() const;
290+
QualType getForgedPtrAsArrayType() const;
179291

180292
QualType getType() const;
181293

@@ -197,6 +309,8 @@ class APValue {
197309
void *TypeInfoType;
198310
/// The QualType, if this is a DynamicAllocLValue.
199311
void *DynamicAllocType;
312+
/// The QualType, if this is a ForgedPtrLValue.
313+
void *ForgedPtrAsArrayType;
200314
};
201315
};
202316

@@ -305,10 +419,45 @@ class APValue {
305419
};
306420
struct MemberPointerData;
307421

422+
/* TO_UPSTREAM(BoundsSafety) ON */
423+
struct LVBase {
424+
APValue::LValueBase Base;
425+
CharUnits Offset;
426+
// BoundsSafety : While the base also holds a corresponding constant array type
427+
// for forged pointer, we still keep track of forged size because the array
428+
// size will be different from the actual forged size if it is not a multiple
429+
// of element type size after a bitcast. The codegen doesn't round up/down
430+
// the bounds to be a type-size multiple, we should keep it the same for
431+
// constant emission. Once __builtin_forge_* has a type as an argument, we
432+
// may consider round down the size with the element type size.
433+
CharUnits ForgedSize;
434+
// While 'Offset' is the offset within the LValue, 'ForgedOffset' is the
435+
// offset of the base pointer of __builtin_unsafe_forge*. For example, in
436+
// the following,
437+
// '__bidi_indexable_unsafe_forge_bidi_indexable(base + N) + M'
438+
// 'N' should be 'ForgedOffset' and 'M' should be 'Offset'. This way, the
439+
// forged pointer itself becomes an LValue starting at base + 'ForgedOffset'.
440+
CharUnits ForgedOffset;
441+
unsigned PathLength;
442+
bool IsNullPtr : 1;
443+
bool IsOnePastTheEnd : 1;
444+
bool IsForgeBidi : 1;
445+
bool IsForgeSingle : 1;
446+
bool IsForgeTerminatedBy : 1;
447+
};
448+
449+
struct LVPlaceHolder {
450+
LVBase Base;
451+
LValuePathEntry Path[1];
452+
};
453+
/* TO_UPSTREAM(BoundsSafety) OFF */
454+
308455
// We ensure elsewhere that Data is big enough for LV and MemberPointerData.
309456
typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
310457
ComplexAPFloat, Vec, Arr, StructData,
311-
UnionData, AddrLabelDiffData> DataType;
458+
UnionData, AddrLabelDiffData,
459+
// TO_UPSTREAM(BoundsSafety)
460+
LVPlaceHolder> DataType;
312461
static const size_t DataSize = sizeof(DataType);
313462

314463
DataType Data;
@@ -487,12 +636,33 @@ class APValue {
487636
const CharUnits &getLValueOffset() const {
488637
return const_cast<APValue*>(this)->getLValueOffset();
489638
}
639+
640+
/* TO_UPSTREAM(BoundsSafety) ON */
641+
CharUnits &getLValueForgedSize();
642+
const CharUnits &getLValueForgedSize() const {
643+
return const_cast<APValue *>(this)->getLValueForgedSize();
644+
}
645+
646+
CharUnits &getLValueForgedOffset();
647+
const CharUnits &getLValueForgedOffset() const {
648+
return const_cast<APValue *>(this)->getLValueForgedOffset();
649+
}
650+
651+
CharUnits getUnwrappedLValueOffset() const;
652+
/* TO_UPSTREAM(BoundsSafety) OFF */
653+
490654
bool isLValueOnePastTheEnd() const;
491655
bool hasLValuePath() const;
492656
ArrayRef<LValuePathEntry> getLValuePath() const;
493657
unsigned getLValueCallIndex() const;
494658
unsigned getLValueVersion() const;
495659
bool isNullPointer() const;
660+
/* TO_UPSTREAM(BoundsSafety) ON */
661+
bool isLValueForgeBidi() const;
662+
bool isLValueForgeSingle() const;
663+
bool isLValueForgeTerminatedBy() const;
664+
bool isLValueForge() const;
665+
/* TO_UPSTREAM(BoundsSafety) OFF */
496666

497667
APValue &getVectorElt(unsigned I) {
498668
assert(isVector() && "Invalid accessor");
@@ -628,6 +798,12 @@ class APValue {
628798
((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr;
629799
}
630800

801+
/* TO_UPSTREAM(BoundsSafety) ON */
802+
void setLValueForgedBidi(const CharUnits &Size, const CharUnits &Offset);
803+
void setLValueForgedSingle(const CharUnits &Offset);
804+
void setLValueForgedTerminatedBy(const CharUnits &Offset);
805+
/* TO_UPSTREAM(BoundsSafety) OFF */
806+
631807
private:
632808
void DestroyDataAndMakeUninit();
633809
void MakeInt() {

0 commit comments

Comments
 (0)