Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 8e77b2b

Browse files
committed
Add an AdjustedType sugar node for adjusting calling conventions
Summary: In general, this type node can be used to represent any type adjustment that occurs implicitly without losing type sugar. The immediate use of this is to adjust the calling conventions of member function pointer types without breaking template instantiation. Fixes PR17996. Reviewers: rsmith Differential Revision: http://llvm-reviews.chandlerc.com/D2332 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196451 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent b8f3702 commit 8e77b2b

25 files changed

+239
-80
lines changed

include/clang/AST/ASTContext.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
8282
mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
8383
mutable llvm::FoldingSet<ComplexType> ComplexTypes;
8484
mutable llvm::FoldingSet<PointerType> PointerTypes;
85-
mutable llvm::FoldingSet<DecayedType> DecayedTypes;
85+
mutable llvm::FoldingSet<AdjustedType> AdjustedTypes;
8686
mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
8787
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
8888
mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
@@ -915,6 +915,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
915915
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
916916
}
917917

918+
/// \brief Return the uniqued reference to a type adjusted from the original
919+
/// type to a new type.
920+
QualType getAdjustedType(QualType Orig, QualType New) const;
921+
CanQualType getAdjustedType(CanQualType Orig, CanQualType New) const {
922+
return CanQualType::CreateUnsafe(
923+
getAdjustedType((QualType)Orig, (QualType)New));
924+
}
925+
918926
/// \brief Return the uniqued reference to the decayed version of the given
919927
/// type. Can only be called on array and function types which decay to
920928
/// pointer types.

include/clang/AST/RecursiveASTVisitor.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,10 @@ DEF_TRAVERSE_TYPE(MemberPointerType, {
874874
TRY_TO(TraverseType(T->getPointeeType()));
875875
})
876876

877+
DEF_TRAVERSE_TYPE(AdjustedType, {
878+
TRY_TO(TraverseType(T->getOriginalType()));
879+
})
880+
877881
DEF_TRAVERSE_TYPE(DecayedType, {
878882
TRY_TO(TraverseType(T->getOriginalType()));
879883
})
@@ -1084,6 +1088,10 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, {
10841088
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
10851089
})
10861090

1091+
DEF_TRAVERSE_TYPELOC(AdjustedType, {
1092+
TRY_TO(TraverseTypeLoc(TL.getOriginalLoc()));
1093+
})
1094+
10871095
DEF_TRAVERSE_TYPELOC(DecayedType, {
10881096
TRY_TO(TraverseTypeLoc(TL.getOriginalLoc()));
10891097
})

include/clang/AST/Type.h

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,39 +1996,59 @@ class PointerType : public Type, public llvm::FoldingSetNode {
19961996
static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
19971997
};
19981998

1999-
/// \brief Represents a pointer type decayed from an array or function type.
2000-
class DecayedType : public Type, public llvm::FoldingSetNode {
2001-
QualType OriginalType;
2002-
QualType DecayedPointer;
1999+
/// \brief Represents a type which was implicitly adjusted by the semantic
2000+
/// engine for arbitrary reasons. For example, array and function types can
2001+
/// decay, and function types can have their calling conventions adjusted.
2002+
class AdjustedType : public Type, public llvm::FoldingSetNode {
2003+
QualType OriginalTy;
2004+
QualType AdjustedTy;
20032005

2004-
DecayedType(QualType OriginalType, QualType DecayedPointer,
2005-
QualType CanonicalPtr)
2006-
: Type(Decayed, CanonicalPtr, OriginalType->isDependentType(),
2007-
OriginalType->isInstantiationDependentType(),
2008-
OriginalType->isVariablyModifiedType(),
2009-
OriginalType->containsUnexpandedParameterPack()),
2010-
OriginalType(OriginalType), DecayedPointer(DecayedPointer) {
2011-
assert(isa<PointerType>(DecayedPointer));
2012-
}
2006+
protected:
2007+
AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy,
2008+
QualType CanonicalPtr)
2009+
: Type(TC, CanonicalPtr, OriginalTy->isDependentType(),
2010+
OriginalTy->isInstantiationDependentType(),
2011+
OriginalTy->isVariablyModifiedType(),
2012+
OriginalTy->containsUnexpandedParameterPack()),
2013+
OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {}
20132014

20142015
friend class ASTContext; // ASTContext creates these.
20152016

20162017
public:
2017-
QualType getDecayedType() const { return DecayedPointer; }
2018-
QualType getOriginalType() const { return OriginalType; }
2019-
2020-
QualType getPointeeType() const {
2021-
return cast<PointerType>(DecayedPointer)->getPointeeType();
2022-
}
2018+
QualType getOriginalType() const { return OriginalTy; }
2019+
QualType getAdjustedType() const { return AdjustedTy; }
20232020

20242021
bool isSugared() const { return true; }
2025-
QualType desugar() const { return DecayedPointer; }
2022+
QualType desugar() const { return AdjustedTy; }
20262023

20272024
void Profile(llvm::FoldingSetNodeID &ID) {
2028-
Profile(ID, OriginalType);
2025+
Profile(ID, OriginalTy, AdjustedTy);
20292026
}
2030-
static void Profile(llvm::FoldingSetNodeID &ID, QualType OriginalType) {
2031-
ID.AddPointer(OriginalType.getAsOpaquePtr());
2027+
static void Profile(llvm::FoldingSetNodeID &ID, QualType Orig, QualType New) {
2028+
ID.AddPointer(Orig.getAsOpaquePtr());
2029+
ID.AddPointer(New.getAsOpaquePtr());
2030+
}
2031+
2032+
static bool classof(const Type *T) {
2033+
return T->getTypeClass() == Adjusted || T->getTypeClass() == Decayed;
2034+
}
2035+
};
2036+
2037+
/// \brief Represents a pointer type decayed from an array or function type.
2038+
class DecayedType : public AdjustedType {
2039+
2040+
DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr)
2041+
: AdjustedType(Decayed, OriginalType, DecayedPtr, CanonicalPtr) {
2042+
assert(isa<PointerType>(getAdjustedType()));
2043+
}
2044+
2045+
friend class ASTContext; // ASTContext creates these.
2046+
2047+
public:
2048+
QualType getDecayedType() const { return getAdjustedType(); }
2049+
2050+
QualType getPointeeType() const {
2051+
return cast<PointerType>(getDecayedType())->getPointeeType();
20322052
}
20332053

20342054
static bool classof(const Type *T) { return T->getTypeClass() == Decayed; }

include/clang/AST/TypeLoc.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -978,12 +978,10 @@ inline TypeLoc TypeLoc::IgnoreParens() const {
978978
}
979979

980980

981-
struct DecayedLocInfo { }; // Nothing.
981+
struct AdjustedLocInfo { }; // Nothing.
982982

983-
/// \brief Wrapper for source info for pointers decayed from arrays and
984-
/// functions.
985-
class DecayedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, DecayedTypeLoc,
986-
DecayedType, DecayedLocInfo> {
983+
class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc,
984+
AdjustedType, AdjustedLocInfo> {
987985
public:
988986
TypeLoc getOriginalLoc() const {
989987
return getInnerTypeLoc();
@@ -1004,12 +1002,17 @@ class DecayedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, DecayedTypeLoc,
10041002
}
10051003

10061004
unsigned getLocalDataSize() const {
1007-
// sizeof(DecayedLocInfo) is 1, but we don't need its address to be unique
1005+
// sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique
10081006
// anyway. TypeLocBuilder can't handle data sizes of 1.
10091007
return 0; // No data.
10101008
}
10111009
};
10121010

1011+
/// \brief Wrapper for source info for pointers decayed from arrays and
1012+
/// functions.
1013+
class DecayedTypeLoc : public InheritingConcreteTypeLoc<
1014+
AdjustedTypeLoc, DecayedTypeLoc, DecayedType> {
1015+
};
10131016

10141017
struct PointerLikeLocInfo {
10151018
SourceLocation StarLoc;

include/clang/AST/TypeNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ TYPE(FunctionNoProto, FunctionType)
8181
DEPENDENT_TYPE(UnresolvedUsing, Type)
8282
NON_CANONICAL_TYPE(Paren, Type)
8383
NON_CANONICAL_TYPE(Typedef, Type)
84-
NON_CANONICAL_TYPE(Decayed, Type)
84+
NON_CANONICAL_TYPE(Adjusted, Type)
85+
NON_CANONICAL_TYPE(Decayed, AdjustedType)
8586
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
8687
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
8788
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)

include/clang/Serialization/ASTBitCodes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,9 @@ namespace clang {
841841
/// \brief An AtomicType record.
842842
TYPE_ATOMIC = 40,
843843
/// \brief A DecayedType record.
844-
TYPE_DECAYED = 41
844+
TYPE_DECAYED = 41,
845+
/// \brief An AdjustedType record.
846+
TYPE_ADJUSTED = 42
845847
};
846848

847849
/// \brief The type IDs for special types constructed by semantic

lib/AST/ASTContext.cpp

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,8 +1632,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
16321632
}
16331633
case Type::ObjCObject:
16341634
return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr());
1635+
case Type::Adjusted:
16351636
case Type::Decayed:
1636-
return getTypeInfo(cast<DecayedType>(T)->getDecayedType().getTypePtr());
1637+
return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr());
16371638
case Type::ObjCInterface: {
16381639
const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
16391640
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
@@ -2163,14 +2164,29 @@ QualType ASTContext::getPointerType(QualType T) const {
21632164
return QualType(New, 0);
21642165
}
21652166

2166-
QualType ASTContext::getDecayedType(QualType T) const {
2167-
assert((T->isArrayType() || T->isFunctionType()) && "T does not decay");
2168-
2167+
QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const {
21692168
llvm::FoldingSetNodeID ID;
2170-
DecayedType::Profile(ID, T);
2169+
AdjustedType::Profile(ID, Orig, New);
21712170
void *InsertPos = 0;
2172-
if (DecayedType *DT = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos))
2173-
return QualType(DT, 0);
2171+
AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
2172+
if (AT)
2173+
return QualType(AT, 0);
2174+
2175+
QualType Canonical = getCanonicalType(New);
2176+
2177+
// Get the new insert position for the node we care about.
2178+
AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
2179+
assert(AT == 0 && "Shouldn't be in the map!");
2180+
2181+
AT = new (*this, TypeAlignment)
2182+
AdjustedType(Type::Adjusted, Orig, New, Canonical);
2183+
Types.push_back(AT);
2184+
AdjustedTypes.InsertNode(AT, InsertPos);
2185+
return QualType(AT, 0);
2186+
}
2187+
2188+
QualType ASTContext::getDecayedType(QualType T) const {
2189+
assert((T->isArrayType() || T->isFunctionType()) && "T does not decay");
21742190

21752191
QualType Decayed;
21762192

@@ -2189,17 +2205,23 @@ QualType ASTContext::getDecayedType(QualType T) const {
21892205
if (T->isFunctionType())
21902206
Decayed = getPointerType(T);
21912207

2208+
llvm::FoldingSetNodeID ID;
2209+
AdjustedType::Profile(ID, T, Decayed);
2210+
void *InsertPos = 0;
2211+
AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
2212+
if (AT)
2213+
return QualType(AT, 0);
2214+
21922215
QualType Canonical = getCanonicalType(Decayed);
21932216

21942217
// Get the new insert position for the node we care about.
2195-
DecayedType *NewIP = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos);
2196-
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
2218+
AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
2219+
assert(AT == 0 && "Shouldn't be in the map!");
21972220

2198-
DecayedType *New =
2199-
new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical);
2200-
Types.push_back(New);
2201-
DecayedTypes.InsertNode(New, InsertPos);
2202-
return QualType(New, 0);
2221+
AT = new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical);
2222+
Types.push_back(AT);
2223+
AdjustedTypes.InsertNode(AT, InsertPos);
2224+
return QualType(AT, 0);
22032225
}
22042226

22052227
/// getBlockPointerType - Return the uniqued reference to the type for

lib/AST/ASTDiagnostic.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
5151
QT = AT->desugar();
5252
continue;
5353
}
54+
// ...or an adjusted type...
55+
if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) {
56+
QT = AT->desugar();
57+
continue;
58+
}
5459
// ... or an auto type.
5560
if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
5661
if (!AT->isSugared())

lib/AST/ASTImporter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,10 +407,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
407407
return false;
408408
break;
409409

410+
case Type::Adjusted:
410411
case Type::Decayed:
411412
if (!IsStructurallyEquivalent(Context,
412-
cast<DecayedType>(T1)->getPointeeType(),
413-
cast<DecayedType>(T2)->getPointeeType()))
413+
cast<AdjustedType>(T1)->getOriginalType(),
414+
cast<AdjustedType>(T2)->getOriginalType()))
414415
return false;
415416
break;
416417

lib/AST/Comment.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,11 @@ void DeclInfo::fill() {
251251
TL = PointerTL.getPointeeLoc().getUnqualifiedLoc();
252252
continue;
253253
}
254+
// Look through adjusted types.
255+
if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) {
256+
TL = ATL.getOriginalLoc();
257+
continue;
258+
}
254259
if (BlockPointerTypeLoc BlockPointerTL =
255260
TL.getAs<BlockPointerTypeLoc>()) {
256261
TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();

0 commit comments

Comments
 (0)