Skip to content

Commit

Permalink
[AST] Rework and simplify getNonProvenanceCarryingType handling
Browse files Browse the repository at this point in the history
This now preserves typedefs where possible, and the generalisation
allows us to remove the special enum case from its caller.
  • Loading branch information
jrtc27 committed Aug 19, 2023
1 parent 0487abc commit b98574d
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 35 deletions.
3 changes: 0 additions & 3 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1103,9 +1103,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
CanQualType IntCapTy, UnsignedIntCapTy;
// Non-provenance carrying intcap_t types
QualType NoProvenanceIntCapTy;
QualType NoProvenanceUnsignedIntCapTy;
CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty, Ibm128Ty;
CanQualType ShortAccumTy, AccumTy,
Expand Down
28 changes: 12 additions & 16 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1334,12 +1334,6 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,

InitBuiltinType(IntCapTy, BuiltinType::IntCap);
InitBuiltinType(UnsignedIntCapTy, BuiltinType::UIntCap);
if (Target.SupportsCapabilities()) {
NoProvenanceIntCapTy =
getAttributedType(attr::CHERINoProvenance, IntCapTy, IntCapTy);
NoProvenanceUnsignedIntCapTy = getAttributedType(
attr::CHERINoProvenance, UnsignedIntCapTy, UnsignedIntCapTy);
}

// GNU extension, __float128 for IEEE quadruple precision
InitBuiltinType(Float128Ty, BuiltinType::Float128);
Expand Down Expand Up @@ -10902,16 +10896,18 @@ QualType ASTContext::getNonProvenanceCarryingType(QualType T) const {
assert(Target->SupportsCapabilities());
// Must be called with either intcap_t or uintcap_t (or atomic variants
// thereof)
if (const AtomicType *AT = dyn_cast<AtomicType>(T.getCanonicalType()))
return getAtomicType(getNonProvenanceCarryingType(AT->getValueType()));
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) {
if (BT->getKind() == BuiltinType::IntCap)
return NoProvenanceIntCapTy;
if (BT->getKind() == BuiltinType::UIntCap)
return NoProvenanceUnsignedIntCapTy;
}
llvm_unreachable("Invalid type passed to getNonProvenanceCarryingType");
return T;
assert(T->isIntCapType() &&
"Invalid type passed to getNonProvenanceCarryingType");
if (const AtomicType *AT = dyn_cast<AtomicType>(T.getDesugaredType(*this))) {
QualType VT = AT->getValueType();
if (VT->hasAttr(attr::CHERINoProvenance))
return T;
return getAtomicType(getNonProvenanceCarryingType(VT));
}
if (T->hasAttr(attr::CHERINoProvenance))
return T;
return const_cast<ASTContext *>(this)->getAttributedType(
attr::CHERINoProvenance, T, T);
}

QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
Expand Down
12 changes: 2 additions & 10 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2135,16 +2135,8 @@ QualType CastExpr::checkProvenanceImpl(QualType Ty, const ASTContext &C,
NPC_ValueDependentIsNotNull))
ExprCanCarryProvenance = false;

if (!ExprCanCarryProvenance) {
// FIXME: allowing __uintcap_t as the underlying type for enums is not
// ideal, as this means we need a const_cast here.
if (Ty->isEnumeralType()) {
return const_cast<ASTContext &>(C).getAttributedType(
attr::CHERINoProvenance, Ty, Ty);
} else {
return C.getNonProvenanceCarryingType(Ty);
}
}
if (!ExprCanCarryProvenance)
return C.getNonProvenanceCarryingType(Ty);
return Ty;
}

Expand Down
18 changes: 18 additions & 0 deletions clang/test/Sema/cheri/atomic-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,21 @@
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:22> '__intcap __attribute__((cheri_no_provenance))':'__intcap' <IntegralCast>
// CHECK-NEXT: IntegerLiteral {{.*}} <col:22> 'int' 0
_Atomic __intcap x = 0;

/// Check we preserve typedefs where possible
typedef __intcap T;
typedef _Atomic T AT;
// CHECK: VarDecl {{.*}} <{{.*}}:[[@LINE+4]]:1, col:8> col:4 y 'AT':'_Atomic(T)' cinit
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:8> '_Atomic(T __attribute__((cheri_no_provenance)))' <NonAtomicToAtomic>
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:8> '__intcap __attribute__((cheri_no_provenance))':'__intcap' <IntegralCast>
// CHECK-NEXT: IntegerLiteral {{.*}} <col:8> 'int' 0
AT y = 0;

/// Check that we don't duplicate attributes when preserving typdefs
typedef __intcap __attribute__((cheri_no_provenance)) TNP;
typedef _Atomic TNP ATNP;
// CHECK: VarDecl {{.*}} <{{.*}}:[[@LINE+4]]:1, col:10> col:6 z 'ATNP':'_Atomic(TNP)' cinit
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:10> 'ATNP':'_Atomic(TNP)' <NonAtomicToAtomic>
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:10> '__intcap __attribute__((cheri_no_provenance))':'__intcap' <IntegralCast>
// CHECK-NEXT: IntegerLiteral {{.*}} <col:10> 'int' 0
ATNP z = 0;
12 changes: 6 additions & 6 deletions clang/test/SemaCXX/cheri/cap-provenance-auto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ typedef __no_provenance unsigned __intcap no_provenance_uintptr_t;

void test_auto(uintptr_t prov, no_provenance_uintptr_t noprov) {
// CHECK-LABEL: {{.+}} test_auto 'void (uintptr_t, no_provenance_uintptr_t)'
auto zero = static_cast<uintptr_t>(0); // CHECK: VarDecl {{.+}} <col:3, col:39> col:8 used zero 'unsigned __intcap __attribute__((cheri_no_provenance))':'unsigned __intcap' cinit{{$}}
const auto const_zero = static_cast<uintptr_t>(0); // CHECK: VarDecl {{.+}} <col:3, col:51> col:14 const_zero 'unsigned __intcap const __attribute__((cheri_no_provenance))':'const unsigned __intcap' cinit{{$}}
auto zero = static_cast<uintptr_t>(0); // CHECK: VarDecl {{.+}} <col:3, col:39> col:8 used zero 'uintptr_t __attribute__((cheri_no_provenance))':'unsigned __intcap' cinit{{$}}
const auto const_zero = static_cast<uintptr_t>(0); // CHECK: VarDecl {{.+}} <col:3, col:51> col:14 const_zero 'uintptr_t const __attribute__((cheri_no_provenance))':'const unsigned __intcap' cinit{{$}}
zero = prov;
zero = prov;
zero = noprov;
Expand All @@ -28,14 +28,14 @@ void test_auto_assign(uintptr_t prov, no_provenance_uintptr_t noprov) {

void test_return_type_lambda(uintptr_t prov, no_provenance_uintptr_t noprov) {
// CHECK-LABEL: {{.+}} test_return_type_lambda 'void (uintptr_t, no_provenance_uintptr_t)'
auto lambda = []() { return static_cast<uintptr_t>(0); }; // CHECK: CXXMethodDecl {{.+}} <col:20, col:58> col:17 used constexpr operator() 'unsigned __intcap () const __attribute__((cheri_no_provenance))' inline
auto from_lambda = lambda(); // CHECK: VarDecl {{.+}} <col:3, col:29> col:8 used from_lambda 'unsigned __intcap __attribute__((cheri_no_provenance))':'unsigned __intcap' cinit{{$}}
const auto const_from_lambda = lambda(); // CHECK: VarDecl {{.+}} <col:3, col:41> col:14 referenced const_from_lambda 'const unsigned __intcap __attribute__((cheri_no_provenance))':'const unsigned __intcap' cinit{{$}}
auto lambda = []() { return static_cast<uintptr_t>(0); }; // CHECK: CXXMethodDecl {{.+}} <col:20, col:58> col:17 used constexpr operator() 'uintptr_t () const __attribute__((cheri_no_provenance))' inline
auto from_lambda = lambda(); // CHECK: VarDecl {{.+}} <col:3, col:29> col:8 used from_lambda 'uintptr_t __attribute__((cheri_no_provenance))':'unsigned __intcap' cinit{{$}}
const auto const_from_lambda = lambda(); // CHECK: VarDecl {{.+}} <col:3, col:41> col:14 referenced const_from_lambda 'const uintptr_t __attribute__((cheri_no_provenance))':'const unsigned __intcap' cinit{{$}}
from_lambda = const_from_lambda;
from_lambda = prov;
from_lambda = noprov;
}

auto return_noprov() { // CHECK: FunctionDecl {{.+}} <line:[[@LINE]]:1, line:[[@LINE+2]]:1> line:[[@LINE]]:6 return_noprov 'unsigned __intcap () __attribute__((cheri_no_provenance))'
auto return_noprov() { // CHECK: FunctionDecl {{.+}} <line:[[@LINE]]:1, line:[[@LINE+2]]:1> line:[[@LINE]]:6 return_noprov 'uintptr_t () __attribute__((cheri_no_provenance))'
return static_cast<uintptr_t>(0);
}

0 comments on commit b98574d

Please sign in to comment.