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

[clang] Extend pointer interpretation handling to track explicitness #714

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
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
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
Loading