Skip to content

Commit

Permalink
[clang] Extend pointer interpretation handling to track explicitness
Browse files Browse the repository at this point in the history
We need a new type like DependentPointerType for non-dependent contexts
that can track __capability applied to things like typeof(...) in order
to have a corresponding TypeLoc for the qualifier, otherwise things like
TypeSpecLocFiller get out of sync and, in some cases assert (in other
cases silently use the wrong DeclSpec). However, this then exposes the
fact TypePrinter's PrintingPolicy's SuppressCapabilityQualifier isn't
always able to be set to the right value (e.g. when printing out a
reinterpret_cast<T> to the user, or when dumping the AST), and so we end
up with redundant __capability qualifiers appearing for purecap code in
some cases, and so we need to track alongside the pointer interpretation
whether it was explicit (which also needs care to ensure it doesn't mess
with canonicalisation). Whilst the output is now noisier in cases where
__capability is used in purecap code, this is more faithful to the
source.

The churn in the AST output due to __capability in the source always
being sugar is an unfortunate side-effect, but this should disappear
if llvm/llvm-project#65214 is merged.

Fixes #710
  • Loading branch information
jrtc27 committed Sep 4, 2023
1 parent 2f2dd31 commit 4d71789
Show file tree
Hide file tree
Showing 72 changed files with 1,516 additions and 935 deletions.
101 changes: 64 additions & 37 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<DependentAddressSpaceType>
DependentAddressSpaceTypes;
mutable llvm::FoldingSet<DependentPointerType> DependentPointerTypes;
mutable llvm::FoldingSet<PointerInterpretationType>
PointerInterpretationTypes;
mutable llvm::FoldingSet<VectorType> VectorTypes;
mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes;
mutable llvm::FoldingSet<ConstantMatrixType> MatrixTypes;
Expand Down Expand Up @@ -1340,19 +1342,42 @@ class ASTContext : public RefCountedBase<ASTContext> {

/// Get the default pointer interpretation in use.
PointerInterpretationKind getDefaultPointerInterpretation() const;
PointerInterpretationKindExplicit
getDefaultPointerInterpretationExplicit() const {
return PointerInterpretationKindExplicit(getDefaultPointerInterpretation(),
/*IsExplicit=*/false);
}

/// Canonicalise a PointerInterpretationKindExplicit, i.e. turn an explicit
/// default interpretation into an implicit one. Do not use when an explicit
/// default interpretation is meaningful.
PointerInterpretationKindExplicit getCanonicalPointerInterpretationExplicit(
PointerInterpretationKindExplicit PIKE) const {
if (PIKE.IsExplicit) {
if (PIKE.PIK == getDefaultPointerInterpretation())
return PointerInterpretationKindExplicit(PIKE.PIK,
/*IsExplicit=*/false);
} else {
assert(PIKE.PIK == getDefaultPointerInterpretation() &&
"Invalid implicit non-default pointer interpretation");
}
return PIKE;
}

/// Return the uniqued reference to the type for a pointer to
/// the specified type.
QualType getPointerType(QualType T,
PointerInterpretationKindExplicit PIKE) const;
QualType getPointerType(QualType T) const {
return getPointerType(T, getDefaultPointerInterpretation());
return getPointerType(T, getDefaultPointerInterpretationExplicit());
}
QualType getPointerType(QualType T, PointerInterpretationKind PIK) const;
// NB: PointerInterpretationKindExplicit-taking variant not present since the
// PIKE may not be canonical, and CanPointerInterpretationKindExplicit
// doesn't exist to ensure the right function is chosen between this and the
// plain QualType version (otherwise this will always be used in preference
// to the QualType one for a CanQualType).
CanQualType getPointerType(CanQualType T) const {
return getPointerType(T, getDefaultPointerInterpretation());
}
CanQualType getPointerType(CanQualType T,
PointerInterpretationKind PIK) const {
return CanQualType::CreateUnsafe(getPointerType((QualType) T, PIK));
return CanQualType::CreateUnsafe(getPointerType((QualType)T));
}

/// Return the uniqued reference to a type adjusted from the original
Expand Down Expand Up @@ -1436,18 +1461,18 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getLValueReferenceType(QualType T,
bool SpelledAsLValue = true) const {
return getLValueReferenceType(T, SpelledAsLValue,
getDefaultPointerInterpretation());
getDefaultPointerInterpretationExplicit());
}
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue,
PointerInterpretationKind PIK) const;
PointerInterpretationKindExplicit PIKE) const;

/// Return the uniqued reference to the type for an rvalue reference
/// to the specified type.
QualType getRValueReferenceType(QualType T) const {
return getRValueReferenceType(T, getDefaultPointerInterpretation());
return getRValueReferenceType(T, getDefaultPointerInterpretationExplicit());
}
QualType getRValueReferenceType(QualType T,
PointerInterpretationKind PIK) const;
PointerInterpretationKindExplicit PIKE) const;

/// Return the uniqued reference to the type for a member pointer to
/// the specified type in the specified class.
Expand All @@ -1457,42 +1482,39 @@ class ASTContext : public RefCountedBase<ASTContext> {

/// Return a non-unique reference to the type for a variable array of
/// the specified element type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals,
SourceRange Brackets,
llvm::Optional<PointerInterpretationKind>
PIK = llvm::None) const;
QualType
getVariableArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals, SourceRange Brackets,
llvm::Optional<PointerInterpretationKindExplicit> PIKE =
llvm::None) const;

/// Return a non-unique reference to the type for a dependently-sized
/// array of the specified element type.
///
/// FIXME: We will need these to be uniqued, or at least comparable, at some
/// point.
QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals,
SourceRange Brackets,
llvm::Optional<PointerInterpretationKind>
PIK = llvm::None) const;
QualType getDependentSizedArrayType(
QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals, SourceRange Brackets,
llvm::Optional<PointerInterpretationKindExplicit> PIKE =
llvm::None) const;

/// Return a unique reference to the type for an incomplete array of
/// the specified element type.
QualType getIncompleteArrayType(QualType EltTy,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals,
llvm::Optional<PointerInterpretationKind>
PIK = llvm::None) const;

QualType getIncompleteArrayType(
QualType EltTy, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals,
llvm::Optional<PointerInterpretationKindExplicit> PIKE =
llvm::None) const;

/// Return the unique reference to the type for a constant array of
/// the specified element type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
const Expr *SizeExpr,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals,
llvm::Optional<PointerInterpretationKind>
PIK = llvm::None) const;
QualType
getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
const Expr *SizeExpr, ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals,
llvm::Optional<PointerInterpretationKindExplicit> PIKE =
llvm::None) const;

/// Return a type for a constant array for a string literal of the
/// specified element type and length.
Expand Down Expand Up @@ -1571,6 +1593,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
PointerInterpretationKind PIK,
SourceLocation QualifierLoc) const;

QualType getPointerInterpretationType(PointerInterpretationKind PIK,
SourceRange QualifierRange,
QualType ModifiedType,
QualType EquivalentType) const;

/// Return a K&R style C function type like 'int()'.
QualType getFunctionNoProtoType(QualType ResultTy,
const FunctionType::ExtInfo &Info) const;
Expand Down Expand Up @@ -2783,8 +2810,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
///
/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
QualType getArrayDecayedType(QualType T,
llvm::Optional<PointerInterpretationKind>
PIKFromBase = llvm::None) const;
llvm::Optional<PointerInterpretationKindExplicit>
PIKEFromBase = llvm::None) const;

/// Return the type that \p PromotableType will promote to: C99
/// 6.3.1.1p2, assuming that \p PromotableType is a promotable integer type.
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/AST/ASTNodeTraverser.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,12 @@ class ASTNodeTraverser
Visit(T->getElementType());
Visit(T->getSizeExpr());
}
void VisitDependentPointerType(const DependentPointerType *T) {
Visit(T->getPointerType());
}
void VisitPointerInterpretationType(const PointerInterpretationType *T) {
Visit(T->getModifiedType());
}
void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); }
void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); }
void VisitFunctionProtoType(const FunctionProtoType *T) {
Expand Down
11 changes: 10 additions & 1 deletion clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -986,9 +986,18 @@ class Expr : public ValueStmt {
return skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
}

/// Returns the PointerInterpretationKindExplicit for the underlying memory
/// access of this expression, if accessing memory.
llvm::Optional<PointerInterpretationKindExplicit>
getUnderlyingPointerInterpretationExplicitOrNone() const;

/// Returns true if the underlying memory of this expression is
/// accessed through a capability.
bool hasUnderlyingCapability() const;
bool hasUnderlyingCapability() const {
llvm::Optional<PointerInterpretationKindExplicit> PIKE =
getUnderlyingPointerInterpretationExplicitOrNone();
return PIKE && PIKE->PIK == PIK_Capability;
}

/// XXXAR: Expr->getType() returns int for the initializers expression in
/// `void x(int& __capability arg) { int& a = arg }`
Expand Down
4 changes: 0 additions & 4 deletions clang/include/clang/AST/PrettyPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ struct PrintingPolicy {
SuppressInlineNamespace(true), SuppressInitializers(false),
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
SuppressCapabilityQualifier(TI && TI->areAllPointersCapabilities()),
SuppressTemplateArgsInCXXConstructors(false),
SuppressDefaultTemplateArgs(true), Bool(LO.Bool),
Nullptr(LO.CPlusPlus11), Restrict(LO.C99), Alignof(LO.CPlusPlus11),
Expand Down Expand Up @@ -182,9 +181,6 @@ struct PrintingPolicy {
/// When true, suppress printing of lifetime qualifier in ARC.
unsigned SuppressLifetimeQualifiers : 1;

/// When true, suppress printing of the __capability qualifier.
unsigned SuppressCapabilityQualifier : 1;

/// When true, suppresses printing template arguments in names of C++
/// constructors.
unsigned SuppressTemplateArgsInCXXConstructors : 1;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/PropertiesBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ def NestedNameSpecifierKind :
EnumPropertyType<"NestedNameSpecifier::SpecifierKind">;
def OverloadedOperatorKind : EnumPropertyType;
def PointerInterpretationKind : EnumPropertyType;
def PointerInterpretationKindExplicit : PropertyType;
def Qualifiers : PropertyType;
def QualType : DefaultValuePropertyType;
def RefQualifierKind : EnumPropertyType;
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,9 @@ DEF_TRAVERSE_TYPE(DependentPointerType, {
TRY_TO(TraverseType(T->getPointerType()));
})

DEF_TRAVERSE_TYPE(PointerInterpretationType,
{ TRY_TO(TraverseType(T->getModifiedType())); })

DEF_TRAVERSE_TYPE(DependentVectorType, {
if (T->getSizeExpr())
TRY_TO(TraverseStmt(T->getSizeExpr()));
Expand Down Expand Up @@ -1199,6 +1202,9 @@ DEF_TRAVERSE_TYPELOC(DependentPointerType, {
TRY_TO(TraverseType(TL.getTypePtr()->getPointerType()));
})

DEF_TRAVERSE_TYPELOC(PointerInterpretationType,
{ TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); })

// FIXME: order? why not size expr first?
// FIXME: base VectorTypeLoc is unfinished
DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, {
Expand Down
Loading

0 comments on commit 4d71789

Please sign in to comment.