Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AST] Handle AtomicType in, rework and simplify ASTContext::getNonProvenanceCarryingType #712

Merged
merged 2 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1123,9 +1123,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
29 changes: 14 additions & 15 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 @@ -10994,15 +10988,20 @@ QualType ASTContext::getNonProvenanceCarryingType(QualType T) const {
// if (!Target->SupportsCapabilities())
// return T; // XXX: should probably assert instead?
assert(Target->SupportsCapabilities());
// Must be called with either intcap_t or uintcap_t
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;
// Must be called with either intcap_t or uintcap_t (or atomic variants
// thereof)
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 @@ -2102,16 +2102,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
28 changes: 28 additions & 0 deletions clang/test/Sema/cheri/atomic-init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: %cheri_cc1 %s -ast-dump | FileCheck %s
// RUN: %cheri_purecap_cc1 %s -ast-dump | FileCheck %s

/// Crashed with "Invalid type passed to getNonProvenanceCarryingType" due to
/// not handling AtomicType
// CHECK: VarDecl {{.*}} <{{.*}}:[[@LINE+4]]:1, col:22> col:18 x '_Atomic(__intcap)' cinit
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:22> '_Atomic(__intcap __attribute__((cheri_no_provenance)))' <NonAtomicToAtomic>
// 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);
}
Loading