summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2013-12-05 01:23:43 +0000
committerReid Kleckner <reid@kleckner.net>2013-12-05 01:23:43 +0000
commit0503a870a94c28ab32fa461e175f8cb387c8718e (patch)
treefa28b29965ee5c660e774fb67830aa8fd3b73e57 /clang/lib
parentd33ff74b196c38ff414773d39899514a9c9dd8ed (diff)
downloadbcm5719-llvm-0503a870a94c28ab32fa461e175f8cb387c8718e.tar.gz
bcm5719-llvm-0503a870a94c28ab32fa461e175f8cb387c8718e.zip
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 llvm-svn: 196451
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp50
-rw-r--r--clang/lib/AST/ASTDiagnostic.cpp5
-rw-r--r--clang/lib/AST/ASTImporter.cpp5
-rw-r--r--clang/lib/AST/Comment.cpp5
-rw-r--r--clang/lib/AST/Decl.cpp7
-rw-r--r--clang/lib/AST/DeclPrinter.cpp3
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp1
-rw-r--r--clang/lib/AST/Type.cpp3
-rw-r--r--clang/lib/AST/TypePrinter.cpp14
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp5
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp4
-rw-r--r--clang/lib/Sema/SemaType.cpp27
-rw-r--r--clang/lib/Sema/TreeTransform.h19
-rw-r--r--clang/lib/Serialization/ASTReader.cpp13
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp9
15 files changed, 131 insertions, 39 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 0528a58f894..79b8770e0b7 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1632,8 +1632,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
}
case Type::ObjCObject:
return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr());
+ case Type::Adjusted:
case Type::Decayed:
- return getTypeInfo(cast<DecayedType>(T)->getDecayedType().getTypePtr());
+ return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr());
case Type::ObjCInterface: {
const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
@@ -2163,14 +2164,29 @@ QualType ASTContext::getPointerType(QualType T) const {
return QualType(New, 0);
}
-QualType ASTContext::getDecayedType(QualType T) const {
- assert((T->isArrayType() || T->isFunctionType()) && "T does not decay");
-
+QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const {
llvm::FoldingSetNodeID ID;
- DecayedType::Profile(ID, T);
+ AdjustedType::Profile(ID, Orig, New);
void *InsertPos = 0;
- if (DecayedType *DT = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(DT, 0);
+ AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (AT)
+ return QualType(AT, 0);
+
+ QualType Canonical = getCanonicalType(New);
+
+ // Get the new insert position for the node we care about.
+ AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(AT == 0 && "Shouldn't be in the map!");
+
+ AT = new (*this, TypeAlignment)
+ AdjustedType(Type::Adjusted, Orig, New, Canonical);
+ Types.push_back(AT);
+ AdjustedTypes.InsertNode(AT, InsertPos);
+ return QualType(AT, 0);
+}
+
+QualType ASTContext::getDecayedType(QualType T) const {
+ assert((T->isArrayType() || T->isFunctionType()) && "T does not decay");
QualType Decayed;
@@ -2189,17 +2205,23 @@ QualType ASTContext::getDecayedType(QualType T) const {
if (T->isFunctionType())
Decayed = getPointerType(T);
+ llvm::FoldingSetNodeID ID;
+ AdjustedType::Profile(ID, T, Decayed);
+ void *InsertPos = 0;
+ AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (AT)
+ return QualType(AT, 0);
+
QualType Canonical = getCanonicalType(Decayed);
// Get the new insert position for the node we care about.
- DecayedType *NewIP = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(AT == 0 && "Shouldn't be in the map!");
- DecayedType *New =
- new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical);
- Types.push_back(New);
- DecayedTypes.InsertNode(New, InsertPos);
- return QualType(New, 0);
+ AT = new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical);
+ Types.push_back(AT);
+ AdjustedTypes.InsertNode(AT, InsertPos);
+ return QualType(AT, 0);
}
/// getBlockPointerType - Return the uniqued reference to the type for
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index ff1aea8a98a..7f7221fc6ed 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -51,6 +51,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
QT = AT->desugar();
continue;
}
+ // ...or an adjusted type...
+ if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) {
+ QT = AT->desugar();
+ continue;
+ }
// ... or an auto type.
if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
if (!AT->isSugared())
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index e16015b7c4e..4292d358164 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -407,10 +407,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
break;
+ case Type::Adjusted:
case Type::Decayed:
if (!IsStructurallyEquivalent(Context,
- cast<DecayedType>(T1)->getPointeeType(),
- cast<DecayedType>(T2)->getPointeeType()))
+ cast<AdjustedType>(T1)->getOriginalType(),
+ cast<AdjustedType>(T2)->getOriginalType()))
return false;
break;
diff --git a/clang/lib/AST/Comment.cpp b/clang/lib/AST/Comment.cpp
index f24a23d34c5..e60eed9630c 100644
--- a/clang/lib/AST/Comment.cpp
+++ b/clang/lib/AST/Comment.cpp
@@ -251,6 +251,11 @@ void DeclInfo::fill() {
TL = PointerTL.getPointeeLoc().getUnqualifiedLoc();
continue;
}
+ // Look through adjusted types.
+ if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) {
+ TL = ATL.getOriginalLoc();
+ continue;
+ }
if (BlockPointerTypeLoc BlockPointerTL =
TL.getAs<BlockPointerTypeLoc>()) {
TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index db3ab9536eb..c75cf20eb38 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2508,11 +2508,8 @@ unsigned FunctionDecl::getBuiltinID() const {
/// based on its FunctionType. This is the length of the ParamInfo array
/// after it has been created.
unsigned FunctionDecl::getNumParams() const {
- const FunctionType *FT = getType()->castAs<FunctionType>();
- if (isa<FunctionNoProtoType>(FT))
- return 0;
- return cast<FunctionProtoType>(FT)->getNumArgs();
-
+ const FunctionProtoType *FPT = getType()->getAs<FunctionProtoType>();
+ return FPT ? FPT->getNumArgs() : 0;
}
void FunctionDecl::setParams(ASTContext &C,
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 767f6620a29..f024f4593ba 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -423,8 +423,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Ty = PT->getInnerType();
}
- if (isa<FunctionType>(Ty)) {
- const FunctionType *AFT = Ty->getAs<FunctionType>();
+ if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
const FunctionProtoType *FT = 0;
if (D->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(AFT);
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index ba67fad6489..e2d334b316d 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -833,6 +833,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
switch (type->getTypeClass()) {
case Type::Builtin:
case Type::Complex:
+ case Type::Adjusted:
case Type::Decayed:
case Type::Pointer:
case Type::BlockPointer:
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 7421bae7bf5..cbb8bc61313 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -593,6 +593,9 @@ namespace {
AutoType *VisitAttributedType(const AttributedType *T) {
return Visit(T->getModifiedType());
}
+ AutoType *VisitAdjustedType(const AdjustedType *T) {
+ return Visit(T->getOriginalType());
+ }
};
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 571e3db0289..082d027791f 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -204,6 +204,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
NeedARCStrongQualifier = true;
// Fall through
+ case Type::Adjusted:
case Type::Decayed:
case Type::Pointer:
case Type::BlockPointer:
@@ -471,12 +472,21 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
printAfter(T->getElementType(), OS);
}
+void TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) {
+ // Print the adjusted representation, otherwise the adjustment will be
+ // invisible.
+ printBefore(T->getAdjustedType(), OS);
+}
+void TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) {
+ printAfter(T->getAdjustedType(), OS);
+}
+
void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) {
// Print as though it's a pointer.
- printBefore(T->getDecayedType(), OS);
+ printAdjustedBefore(T, OS);
}
void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) {
- printAfter(T->getDecayedType(), OS);
+ printAdjustedAfter(T, OS);
}
void TypePrinter::printDependentSizedArrayBefore(
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index fcb26f0da61..451a6848baf 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2123,10 +2123,11 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
return CreateType(cast<ComplexType>(Ty));
case Type::Pointer:
return CreateType(cast<PointerType>(Ty), Unit);
+ case Type::Adjusted:
case Type::Decayed:
- // Decayed types are just pointers in LLVM and DWARF.
+ // Decayed and adjusted types use the adjusted type in LLVM and DWARF.
return CreateType(
- cast<PointerType>(cast<DecayedType>(Ty)->getDecayedType()), Unit);
+ cast<PointerType>(cast<AdjustedType>(Ty)->getAdjustedType()), Unit);
case Type::BlockPointer:
return CreateType(cast<BlockPointerType>(Ty), Unit);
case Type::Typedef:
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index c1dc0b3657f..ce2c9b05c47 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1308,6 +1308,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::ObjCObjectPointer:
llvm_unreachable("type class is never variably-modified!");
+ case Type::Adjusted:
+ type = cast<AdjustedType>(ty)->getAdjustedType();
+ break;
+
case Type::Decayed:
type = cast<DecayedType>(ty)->getPointeeType();
break;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index dd28bfcf7d2..63ac15baeb6 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1812,7 +1812,10 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
}
}
- // FIXME: Adjust member function pointer calling conventions.
+ // Adjust the default free function calling convention to the default method
+ // calling convention.
+ if (T->isFunctionType())
+ adjustMemberFunctionCC(T, /*IsStatic=*/false);
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -3681,6 +3684,9 @@ namespace {
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, Chunk.getAttrs());
}
+ void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ // nothing
+ }
void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
TL.setCaretLoc(Chunk.Loc);
@@ -3836,6 +3842,10 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
+ // FIXME: Ordering here?
+ while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+
DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -4589,14 +4599,15 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
const FunctionType *FT = T->castAs<FunctionType>();
bool IsVariadic = (isa<FunctionProtoType>(FT) &&
cast<FunctionProtoType>(FT)->isVariadic());
- CallingConv CC = FT->getCallConv();
// Only adjust types with the default convention. For example, on Windows we
// should adjust a __cdecl type to __thiscall for instance methods, and a
// __thiscall type to __cdecl for static methods.
- CallingConv DefaultCC =
+ CallingConv CurCC = FT->getCallConv();
+ CallingConv FromCC =
Context.getDefaultCallingConvention(IsVariadic, IsStatic);
- if (CC != DefaultCC)
+ CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
+ if (CurCC != FromCC || FromCC == ToCC)
return;
// Check if there was an explicit attribute, but only look through parens.
@@ -4609,12 +4620,8 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
R = AT->getModifiedType().IgnoreParens();
}
- // FIXME: This loses sugar. This should probably be fixed with an implicit
- // AttributedType node that adjusts the convention.
- CC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
- FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC));
- FunctionTypeUnwrapper Unwrapped(*this, T);
- T = Unwrapped.wrap(*this, FT);
+ FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
+ T = Context.getAdjustedType(T, QualType(FT, T.getQualifiers()));
}
/// Handle OpenCL image access qualifiers: read_only, write_only, read_write
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 44581fd4153..e9cb95006fe 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3664,6 +3664,13 @@ QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
return TransformTypeSpecType(TLB, T);
}
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformAdjustedType(TypeLocBuilder &TLB,
+ AdjustedTypeLoc TL) {
+ // Adjustments applied during transformation are handled elsewhere.
+ return getDerived().TransformType(TLB, TL.getOriginalLoc());
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB,
DecayedTypeLoc TL) {
@@ -3832,6 +3839,14 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
return QualType();
}
+ // If we had to adjust the pointee type when building a member pointer, make
+ // sure to push TypeLoc info for it.
+ const MemberPointerType *MPT = Result->getAs<MemberPointerType>();
+ if (MPT && PointeeType != MPT->getPointeeType()) {
+ assert(isa<AdjustedType>(MPT->getPointeeType()));
+ TLB.push<AdjustedTypeLoc>(MPT->getPointeeType());
+ }
+
MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
NewTL.setSigilLoc(TL.getSigilLoc());
NewTL.setClassTInfo(NewClsTInfo);
@@ -9391,8 +9406,8 @@ QualType
TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
QualType ClassType,
SourceLocation Sigil) {
- return SemaRef.BuildMemberPointerType(PointeeType, ClassType,
- Sigil, getDerived().getBaseEntity());
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil,
+ getDerived().getBaseEntity());
}
template<typename Derived>
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 4d1b4b90b66..c531134a974 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4548,6 +4548,16 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
return DT;
}
+ case TYPE_ADJUSTED: {
+ if (Record.size() != 2) {
+ Error("Incorrect encoding of adjusted type");
+ return QualType();
+ }
+ QualType OriginalTy = readType(*Loc.F, Record, Idx);
+ QualType AdjustedTy = readType(*Loc.F, Record, Idx);
+ return Context.getAdjustedType(OriginalTy, AdjustedTy);
+ }
+
case TYPE_BLOCK_POINTER: {
if (Record.size() != 1) {
Error("Incorrect encoding of block pointer type");
@@ -4997,6 +5007,9 @@ void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
void TypeLocReader::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
// nothing to do
}
+void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ // nothing to do
+}
void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
TL.setCaretLoc(ReadSourceLocation(Record, Idx));
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index fa5b83d98fb..d8f170fd517 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -113,6 +113,12 @@ void ASTTypeWriter::VisitDecayedType(const DecayedType *T) {
Code = TYPE_DECAYED;
}
+void ASTTypeWriter::VisitAdjustedType(const AdjustedType *T) {
+ Writer.AddTypeRef(T->getOriginalType(), Record);
+ Writer.AddTypeRef(T->getAdjustedType(), Record);
+ Code = TYPE_ADJUSTED;
+}
+
void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
Code = TYPE_BLOCK_POINTER;
@@ -455,6 +461,9 @@ void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
// nothing to do
}
+void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ // nothing to do
+}
void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
Writer.AddSourceLocation(TL.getCaretLoc(), Record);
}
OpenPOWER on IntegriCloud