summaryrefslogtreecommitdiffstats
path: root/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r--lib/AST/ASTContext.cpp550
1 files changed, 307 insertions, 243 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index eea727d..851f8d1 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/Builtins.h"
@@ -27,7 +28,6 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "RecordLayoutBuilder.h"
using namespace clang;
@@ -46,7 +46,9 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t),
Idents(idents), Selectors(sels),
- BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts),
+ BuiltinInfo(builtins),
+ DeclarationNames(*this),
+ ExternalSource(0), PrintingPolicy(LOpts),
LastSDM(0, 0) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
@@ -61,6 +63,12 @@ ASTContext::~ASTContext() {
// FIXME: Is this the ideal solution?
ReleaseDeclContextMaps();
+ if (!FreeMemory) {
+ // Call all of the deallocation functions.
+ for (unsigned I = 0, N = Deallocations.size(); I != N; ++I)
+ Deallocations[I].first(Deallocations[I].second);
+ }
+
// Release all of the memory associated with overridden C++ methods.
for (llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::iterator
OM = OverriddenMethods.begin(), OMEnd = OverriddenMethods.end();
@@ -111,6 +119,10 @@ ASTContext::~ASTContext() {
TUDecl->Destroy(*this);
}
+void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
+ Deallocations.push_back(std::make_pair(Callback, Data));
+}
+
void
ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) {
ExternalSource.reset(Source.take());
@@ -419,6 +431,18 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
return CharUnits::fromQuantity(Align / Target.getCharWidth());
}
+std::pair<CharUnits, CharUnits>
+ASTContext::getTypeInfoInChars(const Type *T) {
+ std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
+ return std::make_pair(CharUnits::fromQuantity(Info.first / getCharWidth()),
+ CharUnits::fromQuantity(Info.second / getCharWidth()));
+}
+
+std::pair<CharUnits, CharUnits>
+ASTContext::getTypeInfoInChars(QualType T) {
+ return getTypeInfoInChars(T.getTypePtr());
+}
+
/// getTypeSize - Return the size of the specified type, in bits. This method
/// does not work on incomplete types.
///
@@ -593,6 +617,8 @@ ASTContext::getTypeInfo(const Type *T) {
Align = EltInfo.second;
break;
}
+ case Type::ObjCObject:
+ return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr());
case Type::ObjCInterface: {
const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
@@ -624,10 +650,6 @@ ASTContext::getTypeInfo(const Type *T) {
return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
getReplacementType().getTypePtr());
- case Type::Elaborated:
- return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType()
- .getTypePtr());
-
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
@@ -650,8 +672,8 @@ ASTContext::getTypeInfo(const Type *T) {
return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType()
.getTypePtr());
- case Type::QualifiedName:
- return getTypeInfo(cast<QualifiedNameType>(T)->getNamedType().getTypePtr());
+ case Type::Elaborated:
+ return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
case Type::TemplateSpecialization:
assert(getCanonicalType(T) != T &&
@@ -875,40 +897,6 @@ TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T,
return DI;
}
-/// getInterfaceLayoutImpl - Get or compute information about the
-/// layout of the given interface.
-///
-/// \param Impl - If given, also include the layout of the interface's
-/// implementation. This may differ by including synthesized ivars.
-const ASTRecordLayout &
-ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
- const ObjCImplementationDecl *Impl) {
- assert(!D->isForwardDecl() && "Invalid interface decl!");
-
- // Look up this layout, if already laid out, return what we have.
- ObjCContainerDecl *Key =
- Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D;
- if (const ASTRecordLayout *Entry = ObjCLayouts[Key])
- return *Entry;
-
- // Add in synthesized ivar count if laying out an implementation.
- if (Impl) {
- unsigned SynthCount = CountNonClassIvars(D);
- // If there aren't any sythesized ivars then reuse the interface
- // entry. Note we can't cache this because we simply free all
- // entries later; however we shouldn't look up implementations
- // frequently.
- if (SynthCount == 0)
- return getObjCLayout(D, 0);
- }
-
- const ASTRecordLayout *NewEntry =
- ASTRecordLayoutBuilder::ComputeLayout(*this, D, Impl);
- ObjCLayouts[Key] = NewEntry;
-
- return *NewEntry;
-}
-
const ASTRecordLayout &
ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) {
return getObjCLayout(D, 0);
@@ -919,45 +907,6 @@ ASTContext::getASTObjCImplementationLayout(const ObjCImplementationDecl *D) {
return getObjCLayout(D->getClassInterface(), D);
}
-/// getASTRecordLayout - Get or compute information about the layout of the
-/// specified record (struct/union/class), which indicates its size and field
-/// position information.
-const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
- D = D->getDefinition();
- assert(D && "Cannot get layout of forward declarations!");
-
- // Look up this layout, if already laid out, return what we have.
- // Note that we can't save a reference to the entry because this function
- // is recursive.
- const ASTRecordLayout *Entry = ASTRecordLayouts[D];
- if (Entry) return *Entry;
-
- const ASTRecordLayout *NewEntry =
- ASTRecordLayoutBuilder::ComputeLayout(*this, D);
- ASTRecordLayouts[D] = NewEntry;
-
- if (getLangOptions().DumpRecordLayouts) {
- llvm::errs() << "\n*** Dumping AST Record Layout\n";
- DumpRecordLayout(D, llvm::errs());
- }
-
- return *NewEntry;
-}
-
-const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
- RD = cast<CXXRecordDecl>(RD->getDefinition());
- assert(RD && "Cannot get key function for forward declarations!");
-
- const CXXMethodDecl *&Entry = KeyFunctions[RD];
- if (!Entry)
- Entry = ASTRecordLayoutBuilder::ComputeKeyFunction(RD);
- else
- assert(Entry == ASTRecordLayoutBuilder::ComputeKeyFunction(RD) &&
- "Key function changed!");
-
- return Entry;
-}
-
//===----------------------------------------------------------------------===//
// Type creation/memoization methods
//===----------------------------------------------------------------------===//
@@ -1343,9 +1292,17 @@ QualType ASTContext::getVariableArrayType(QualType EltTy,
SourceRange Brackets) {
// Since we don't unique expressions, it isn't possible to unique VLA's
// that have an expression provided for their size.
-
+ QualType CanonType;
+
+ if (!EltTy.isCanonical()) {
+ if (NumElts)
+ NumElts->Retain();
+ CanonType = getVariableArrayType(getCanonicalType(EltTy), NumElts, ASM,
+ EltTypeQuals, Brackets);
+ }
+
VariableArrayType *New = new(*this, TypeAlignment)
- VariableArrayType(EltTy, QualType(), NumElts, ASM, EltTypeQuals, Brackets);
+ VariableArrayType(EltTy, CanonType, NumElts, ASM, EltTypeQuals, Brackets);
VariableArrayTypes.push_back(New);
Types.push_back(New);
@@ -1694,10 +1651,6 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) {
if (const TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Decl))
return getTypedefType(Typedef);
- if (const ObjCInterfaceDecl *ObjCInterface
- = dyn_cast<ObjCInterfaceDecl>(Decl))
- return getObjCInterfaceType(ObjCInterface);
-
assert(!isa<TemplateTypeParmDecl>(Decl) &&
"Template type parameter types are always available.");
@@ -1888,29 +1841,28 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
}
QualType
-ASTContext::getQualifiedNameType(NestedNameSpecifier *NNS,
- QualType NamedType) {
+ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ QualType NamedType) {
llvm::FoldingSetNodeID ID;
- QualifiedNameType::Profile(ID, NNS, NamedType);
+ ElaboratedType::Profile(ID, Keyword, NNS, NamedType);
void *InsertPos = 0;
- QualifiedNameType *T
- = QualifiedNameTypes.FindNodeOrInsertPos(ID, InsertPos);
+ ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
return QualType(T, 0);
QualType Canon = NamedType;
if (!Canon.isCanonical()) {
Canon = getCanonicalType(NamedType);
- QualifiedNameType *CheckT
- = QualifiedNameTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(!CheckT && "Qualified name canonical type broken");
+ ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!CheckT && "Elaborated canonical type broken");
(void)CheckT;
}
- T = new (*this) QualifiedNameType(NNS, NamedType, Canon);
+ T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon);
Types.push_back(T);
- QualifiedNameTypes.InsertNode(T, InsertPos);
+ ElaboratedTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
}
@@ -1987,30 +1939,6 @@ ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
return QualType(T, 0);
}
-QualType
-ASTContext::getElaboratedType(QualType UnderlyingType,
- ElaboratedType::TagKind Tag) {
- llvm::FoldingSetNodeID ID;
- ElaboratedType::Profile(ID, UnderlyingType, Tag);
-
- void *InsertPos = 0;
- ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
- if (T)
- return QualType(T, 0);
-
- QualType Canon = UnderlyingType;
- if (!Canon.isCanonical()) {
- Canon = getCanonicalType(Canon);
- ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(!CheckT && "Elaborated canonical type is broken"); (void)CheckT;
- }
-
- T = new (*this) ElaboratedType(UnderlyingType, Tag, Canon);
- Types.push_back(T);
- ElaboratedTypes.InsertNode(T, InsertPos);
- return QualType(T, 0);
-}
-
/// CmpProtocolNames - Comparison predicate for sorting protocols
/// alphabetically.
static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
@@ -2018,7 +1946,7 @@ static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
return LHS->getDeclName() < RHS->getDeclName();
}
-static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols,
+static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) {
if (NumProtocols == 0) return true;
@@ -2040,96 +1968,98 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
NumProtocols = ProtocolsEnd-Protocols;
}
-/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
-/// the given interface decl and the conforming protocol list.
-QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
- ObjCProtocolDecl **Protocols,
- unsigned NumProtocols,
- unsigned Quals) {
- llvm::FoldingSetNodeID ID;
- ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols);
- Qualifiers Qs = Qualifiers::fromCVRMask(Quals);
+QualType ASTContext::getObjCObjectType(QualType BaseType,
+ ObjCProtocolDecl * const *Protocols,
+ unsigned NumProtocols) {
+ // If the base type is an interface and there aren't any protocols
+ // to add, then the interface type will do just fine.
+ if (!NumProtocols && isa<ObjCInterfaceType>(BaseType))
+ return BaseType;
+ // Look in the folding set for an existing type.
+ llvm::FoldingSetNodeID ID;
+ ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols);
void *InsertPos = 0;
- if (ObjCObjectPointerType *QT =
- ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
- return getQualifiedType(QualType(QT, 0), Qs);
+ if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(QT, 0);
- // Sort the protocol list alphabetically to canonicalize it.
+ // Build the canonical type, which has the canonical base type and
+ // a sorted-and-uniqued list of protocols.
QualType Canonical;
- if (!InterfaceT.isCanonical() ||
- !areSortedAndUniqued(Protocols, NumProtocols)) {
- if (!areSortedAndUniqued(Protocols, NumProtocols)) {
+ bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols);
+ if (!ProtocolsSorted || !BaseType.isCanonical()) {
+ if (!ProtocolsSorted) {
llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
Protocols + NumProtocols);
unsigned UniqueCount = NumProtocols;
SortAndUniqueProtocols(&Sorted[0], UniqueCount);
-
- Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
- &Sorted[0], UniqueCount);
+ Canonical = getObjCObjectType(getCanonicalType(BaseType),
+ &Sorted[0], UniqueCount);
} else {
- Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
- Protocols, NumProtocols);
+ Canonical = getObjCObjectType(getCanonicalType(BaseType),
+ Protocols, NumProtocols);
}
// Regenerate InsertPos.
- ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+ ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos);
}
- // No match.
- unsigned Size = sizeof(ObjCObjectPointerType)
- + NumProtocols * sizeof(ObjCProtocolDecl *);
+ unsigned Size = sizeof(ObjCObjectTypeImpl);
+ Size += NumProtocols * sizeof(ObjCProtocolDecl *);
void *Mem = Allocate(Size, TypeAlignment);
- ObjCObjectPointerType *QType = new (Mem) ObjCObjectPointerType(Canonical,
- InterfaceT,
- Protocols,
- NumProtocols);
+ ObjCObjectTypeImpl *T =
+ new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols);
- Types.push_back(QType);
- ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
- return getQualifiedType(QualType(QType, 0), Qs);
+ Types.push_back(T);
+ ObjCObjectTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
}
-/// getObjCInterfaceType - Return the unique reference to the type for the
-/// specified ObjC interface decl. The list of protocols is optional.
-QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
- ObjCProtocolDecl **Protocols, unsigned NumProtocols) {
+/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
+/// the given object type.
+QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) {
llvm::FoldingSetNodeID ID;
- ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols);
+ ObjCObjectPointerType::Profile(ID, ObjectT);
void *InsertPos = 0;
- if (ObjCInterfaceType *QT =
- ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos))
+ if (ObjCObjectPointerType *QT =
+ ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
- // Sort the protocol list alphabetically to canonicalize it.
+ // Find the canonical object type.
QualType Canonical;
- if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) {
- llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
- Protocols + NumProtocols);
-
- unsigned UniqueCount = NumProtocols;
- SortAndUniqueProtocols(&Sorted[0], UniqueCount);
+ if (!ObjectT.isCanonical()) {
+ Canonical = getObjCObjectPointerType(getCanonicalType(ObjectT));
- Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount);
-
- ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos);
+ // Regenerate InsertPos.
+ ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
}
- unsigned Size = sizeof(ObjCInterfaceType)
- + NumProtocols * sizeof(ObjCProtocolDecl *);
- void *Mem = Allocate(Size, TypeAlignment);
- ObjCInterfaceType *QType = new (Mem) ObjCInterfaceType(Canonical,
- const_cast<ObjCInterfaceDecl*>(Decl),
- Protocols,
- NumProtocols);
+ // No match.
+ void *Mem = Allocate(sizeof(ObjCObjectPointerType), TypeAlignment);
+ ObjCObjectPointerType *QType =
+ new (Mem) ObjCObjectPointerType(Canonical, ObjectT);
Types.push_back(QType);
- ObjCInterfaceTypes.InsertNode(QType, InsertPos);
+ ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
return QualType(QType, 0);
}
+/// getObjCInterfaceType - Return the unique reference to the type for the
+/// specified ObjC interface decl. The list of protocols is optional.
+QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) {
+ if (Decl->TypeForDecl)
+ return QualType(Decl->TypeForDecl, 0);
+
+ // FIXME: redeclarations?
+ void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment);
+ ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl);
+ Decl->TypeForDecl = T;
+ Types.push_back(T);
+ return QualType(T, 0);
+}
+
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
/// TypeOfExprType AST's (since expression's are never shared). For example,
/// multiple declarations that refer to "typeof(x)" all contain different
@@ -2362,26 +2292,35 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
QualType ASTContext::getUnqualifiedArrayType(QualType T,
Qualifiers &Quals) {
Quals = T.getQualifiers();
- if (!isa<ArrayType>(T)) {
+ const ArrayType *AT = getAsArrayType(T);
+ if (!AT) {
return T.getUnqualifiedType();
}
- const ArrayType *AT = cast<ArrayType>(T);
QualType Elt = AT->getElementType();
QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals);
if (Elt == UnqualElt)
return T;
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
return getConstantArrayType(UnqualElt, CAT->getSize(),
CAT->getSizeModifier(), 0);
}
- if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
+ if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
return getIncompleteArrayType(UnqualElt, IAT->getSizeModifier(), 0);
}
- const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) {
+ return getVariableArrayType(UnqualElt,
+ VAT->getSizeExpr() ?
+ VAT->getSizeExpr()->Retain() : 0,
+ VAT->getSizeModifier(),
+ VAT->getIndexTypeCVRQualifiers(),
+ VAT->getBracketsRange());
+ }
+
+ const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(AT);
return getDependentSizedArrayType(UnqualElt, DSAT->getSizeExpr()->Retain(),
DSAT->getSizeModifier(), 0,
SourceRange());
@@ -2716,6 +2655,9 @@ unsigned ASTContext::getIntegerRank(Type *T) {
/// \returns the type this bit-field will promote to, or NULL if no
/// promotion occurs.
QualType ASTContext::isPromotableBitField(Expr *E) {
+ if (E->isTypeDependent() || E->isValueDependent())
+ return QualType();
+
FieldDecl *Field = E->getBitField();
if (!Field)
return QualType();
@@ -2811,7 +2753,7 @@ CreateRecordDecl(ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC,
QualType ASTContext::getCFConstantStringType() {
if (!CFConstantStringTypeDecl) {
CFConstantStringTypeDecl =
- CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
&Idents.get("NSConstantString"));
CFConstantStringTypeDecl->startDefinition();
@@ -2853,7 +2795,7 @@ void ASTContext::setCFConstantStringType(QualType T) {
QualType ASTContext::getNSConstantStringType() {
if (!NSConstantStringTypeDecl) {
NSConstantStringTypeDecl =
- CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
&Idents.get("__builtin_NSString"));
NSConstantStringTypeDecl->startDefinition();
@@ -2892,7 +2834,7 @@ void ASTContext::setNSConstantStringType(QualType T) {
QualType ASTContext::getObjCFastEnumerationStateType() {
if (!ObjCFastEnumerationStateTypeDecl) {
ObjCFastEnumerationStateTypeDecl =
- CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
&Idents.get("__objcFastEnumerationState"));
ObjCFastEnumerationStateTypeDecl->startDefinition();
@@ -2927,7 +2869,7 @@ QualType ASTContext::getBlockDescriptorType() {
RecordDecl *T;
// FIXME: Needs the FlagAppleBlock bit.
- T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
&Idents.get("__block_descriptor"));
T->startDefinition();
@@ -2972,7 +2914,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() {
RecordDecl *T;
// FIXME: Needs the FlagAppleBlock bit.
- T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
&Idents.get("__block_descriptor_withcopydispose"));
T->startDefinition();
@@ -3044,7 +2986,7 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
++UniqueBlockByRefTypeID << '_' << DeclName;
RecordDecl *T;
- T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
&Idents.get(Name.str()));
T->startDefinition();
QualType Int32Ty = IntTy;
@@ -3088,14 +3030,15 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
QualType ASTContext::getBlockParmType(
bool BlockHasCopyDispose,
- llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) {
+ llvm::SmallVectorImpl<const Expr *> &Layout) {
+
// FIXME: Move up
static unsigned int UniqueBlockParmTypeID = 0;
llvm::SmallString<36> Name;
llvm::raw_svector_ostream(Name) << "__block_literal_"
<< ++UniqueBlockParmTypeID;
RecordDecl *T;
- T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
&Idents.get(Name.str()));
T->startDefinition();
QualType FieldTypes[] = {
@@ -3125,22 +3068,28 @@ QualType ASTContext::getBlockParmType(
T->addDecl(Field);
}
- for (size_t i = 0; i < BlockDeclRefDecls.size(); ++i) {
- const Expr *E = BlockDeclRefDecls[i];
- const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
- clang::IdentifierInfo *Name = 0;
- if (BDRE) {
+ for (unsigned i = 0; i < Layout.size(); ++i) {
+ const Expr *E = Layout[i];
+
+ QualType FieldType = E->getType();
+ IdentifierInfo *FieldName = 0;
+ if (isa<CXXThisExpr>(E)) {
+ FieldName = &Idents.get("this");
+ } else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E)) {
const ValueDecl *D = BDRE->getDecl();
- Name = &Idents.get(D->getName());
+ FieldName = D->getIdentifier();
+ if (BDRE->isByRef())
+ FieldType = BuildByRefType(D->getNameAsCString(), FieldType);
+ } else {
+ // Padding.
+ assert(isa<ConstantArrayType>(FieldType) &&
+ isa<DeclRefExpr>(E) &&
+ !cast<DeclRefExpr>(E)->getDecl()->getDeclName() &&
+ "doesn't match characteristics of padding decl");
}
- QualType FieldType = E->getType();
-
- if (BDRE && BDRE->isByRef())
- FieldType = BuildByRefType(BDRE->getDecl()->getNameAsCString(),
- FieldType);
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
- Name, FieldType, /*TInfo=*/0,
+ FieldName, FieldType, /*TInfo=*/0,
/*BitWidth=*/0, /*Mutable=*/false);
Field->setAccess(AS_public);
T->addDecl(Field);
@@ -3593,6 +3542,17 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
// Anonymous structures print as '?'
if (const IdentifierInfo *II = RDecl->getIdentifier()) {
S += II->getName();
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ std::string TemplateArgsStr
+ = TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size(),
+ (*this).PrintingPolicy);
+
+ S += TemplateArgsStr;
+ }
} else {
S += '?';
}
@@ -3636,6 +3596,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
return;
}
+ // Ignore protocol qualifiers when mangling at this level.
+ if (const ObjCObjectType *OT = T->getAs<ObjCObjectType>())
+ T = OT->getBaseType();
+
if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
// @encode(class_name)
ObjCInterfaceDecl *OI = OIT->getDecl();
@@ -3718,6 +3682,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
return;
}
+ // gcc just blithely ignores member pointers.
+ // TODO: maybe there should be a mangling for these
+ if (T->getAs<MemberPointerType>())
+ return;
+
assert(0 && "@encode for type not implemented!");
}
@@ -4106,18 +4075,21 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
///
bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT) {
+ const ObjCObjectType* LHS = LHSOPT->getObjectType();
+ const ObjCObjectType* RHS = RHSOPT->getObjectType();
+
// If either type represents the built-in 'id' or 'Class' types, return true.
- if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType())
+ if (LHS->isObjCUnqualifiedIdOrClass() ||
+ RHS->isObjCUnqualifiedIdOrClass())
return true;
- if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
+ if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId())
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false);
- const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
- const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
- if (LHS && RHS) // We have 2 user-defined types.
+ // If we have 2 user-defined types, fall into that path.
+ if (LHS->getInterface() && RHS->getInterface())
return canAssignObjCInterfaces(LHS, RHS);
return false;
@@ -4168,8 +4140,10 @@ void getIntersectionOfProtocols(ASTContext &Context,
const ObjCObjectPointerType *RHSOPT,
llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
- const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
- const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+ const ObjCObjectType* LHS = LHSOPT->getObjectType();
+ const ObjCObjectType* RHS = RHSOPT->getObjectType();
+ assert(LHS->getInterface() && "LHS must have an interface base");
+ assert(RHS->getInterface() && "RHS must have an interface base");
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
unsigned LHSNumProtocols = LHS->getNumProtocols();
@@ -4177,7 +4151,8 @@ void getIntersectionOfProtocols(ASTContext &Context,
InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
else {
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
- Context.CollectInheritedProtocols(LHS->getDecl(), LHSInheritedProtocols);
+ Context.CollectInheritedProtocols(LHS->getInterface(),
+ LHSInheritedProtocols);
InheritedProtocolSet.insert(LHSInheritedProtocols.begin(),
LHSInheritedProtocols.end());
}
@@ -4192,7 +4167,8 @@ void getIntersectionOfProtocols(ASTContext &Context,
}
else {
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
- Context.CollectInheritedProtocols(RHS->getDecl(), RHSInheritedProtocols);
+ Context.CollectInheritedProtocols(RHS->getInterface(),
+ RHSInheritedProtocols);
for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
RHSInheritedProtocols.begin(),
E = RHSInheritedProtocols.end(); I != E; ++I)
@@ -4206,37 +4182,40 @@ void getIntersectionOfProtocols(ASTContext &Context,
/// last type comparison in a ?-exp of ObjC pointer types before a
/// warning is issued. So, its invokation is extremely rare.
QualType ASTContext::areCommonBaseCompatible(
- const ObjCObjectPointerType *LHSOPT,
- const ObjCObjectPointerType *RHSOPT) {
- const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
- const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
- if (!LHS || !RHS)
+ const ObjCObjectPointerType *Lptr,
+ const ObjCObjectPointerType *Rptr) {
+ const ObjCObjectType *LHS = Lptr->getObjectType();
+ const ObjCObjectType *RHS = Rptr->getObjectType();
+ const ObjCInterfaceDecl* LDecl = LHS->getInterface();
+ const ObjCInterfaceDecl* RDecl = RHS->getInterface();
+ if (!LDecl || !RDecl)
return QualType();
- while (const ObjCInterfaceDecl *LHSIDecl = LHS->getDecl()->getSuperClass()) {
- QualType LHSTy = getObjCInterfaceType(LHSIDecl);
- LHS = LHSTy->getAs<ObjCInterfaceType>();
+ while ((LDecl = LDecl->getSuperClass())) {
+ LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl));
if (canAssignObjCInterfaces(LHS, RHS)) {
- llvm::SmallVector<ObjCProtocolDecl *, 8> IntersectionOfProtocols;
- getIntersectionOfProtocols(*this,
- LHSOPT, RHSOPT, IntersectionOfProtocols);
- if (IntersectionOfProtocols.empty())
- LHSTy = getObjCObjectPointerType(LHSTy);
- else
- LHSTy = getObjCObjectPointerType(LHSTy, &IntersectionOfProtocols[0],
- IntersectionOfProtocols.size());
- return LHSTy;
+ llvm::SmallVector<ObjCProtocolDecl *, 8> Protocols;
+ getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols);
+
+ QualType Result = QualType(LHS, 0);
+ if (!Protocols.empty())
+ Result = getObjCObjectType(Result, Protocols.data(), Protocols.size());
+ Result = getObjCObjectPointerType(Result);
+ return Result;
}
}
return QualType();
}
-bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
- const ObjCInterfaceType *RHS) {
+bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
+ const ObjCObjectType *RHS) {
+ assert(LHS->getInterface() && "LHS is not an interface type");
+ assert(RHS->getInterface() && "RHS is not an interface type");
+
// Verify that the base decls are compatible: the RHS must be a subclass of
// the LHS.
- if (!LHS->getDecl()->isSuperClassOf(RHS->getDecl()))
+ if (!LHS->getInterface()->isSuperClassOf(RHS->getInterface()))
return false;
// RHS must have a superset of the protocols in the LHS. If the LHS is not
@@ -4249,15 +4228,15 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
if (RHS->getNumProtocols() == 0)
return true; // FIXME: should return false!
- for (ObjCInterfaceType::qual_iterator LHSPI = LHS->qual_begin(),
- LHSPE = LHS->qual_end();
+ for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
+ LHSPE = LHS->qual_end();
LHSPI != LHSPE; LHSPI++) {
bool RHSImplementsProtocol = false;
// If the RHS doesn't implement the protocol on the left, the types
// are incompatible.
- for (ObjCInterfaceType::qual_iterator RHSPI = RHS->qual_begin(),
- RHSPE = RHS->qual_end();
+ for (ObjCObjectType::qual_iterator RHSPI = RHS->qual_begin(),
+ RHSPE = RHS->qual_end();
RHSPI != RHSPE; RHSPI++) {
if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) {
RHSImplementsProtocol = true;
@@ -4483,6 +4462,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
if (RHSClass == Type::VariableArray || RHSClass == Type::IncompleteArray)
RHSClass = Type::ConstantArray;
+ // ObjCInterfaces are just specialized ObjCObjects.
+ if (LHSClass == Type::ObjCInterface) LHSClass = Type::ObjCObject;
+ if (RHSClass == Type::ObjCInterface) RHSClass = Type::ObjCObject;
+
// Canonicalize ExtVector -> Vector.
if (LHSClass == Type::ExtVector) LHSClass = Type::Vector;
if (RHSClass == Type::ExtVector) RHSClass = Type::Vector;
@@ -4522,6 +4505,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
assert(false && "C++ should never be in mergeTypes");
return QualType();
+ case Type::ObjCInterface:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::FunctionProto:
@@ -4614,14 +4598,13 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
RHSCan->getAs<VectorType>()))
return LHS;
return QualType();
- case Type::ObjCInterface: {
- // Check if the interfaces are assignment compatible.
+ case Type::ObjCObject: {
+ // Check if the types are assignment compatible.
// FIXME: This should be type compatibility, e.g. whether
// "LHS x; RHS x;" at global scope is legal.
- const ObjCInterfaceType* LHSIface = LHS->getAs<ObjCInterfaceType>();
- const ObjCInterfaceType* RHSIface = RHS->getAs<ObjCInterfaceType>();
- if (LHSIface && RHSIface &&
- canAssignObjCInterfaces(LHSIface, RHSIface))
+ const ObjCObjectType* LHSIface = LHS->getAs<ObjCObjectType>();
+ const ObjCObjectType* RHSIface = RHS->getAs<ObjCObjectType>();
+ if (canAssignObjCInterfaces(LHSIface, RHSIface))
return LHS;
return QualType();
@@ -4645,6 +4628,87 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return QualType();
}
+/// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and
+/// 'RHS' attributes and returns the merged version; including for function
+/// return types.
+QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
+ QualType LHSCan = getCanonicalType(LHS),
+ RHSCan = getCanonicalType(RHS);
+ // If two types are identical, they are compatible.
+ if (LHSCan == RHSCan)
+ return LHS;
+ if (RHSCan->isFunctionType()) {
+ if (!LHSCan->isFunctionType())
+ return QualType();
+ QualType OldReturnType =
+ cast<FunctionType>(RHSCan.getTypePtr())->getResultType();
+ QualType NewReturnType =
+ cast<FunctionType>(LHSCan.getTypePtr())->getResultType();
+ QualType ResReturnType =
+ mergeObjCGCQualifiers(NewReturnType, OldReturnType);
+ if (ResReturnType.isNull())
+ return QualType();
+ if (ResReturnType == NewReturnType || ResReturnType == OldReturnType) {
+ // id foo(); ... __strong id foo(); or: __strong id foo(); ... id foo();
+ // In either case, use OldReturnType to build the new function type.
+ const FunctionType *F = LHS->getAs<FunctionType>();
+ if (const FunctionProtoType *FPT = cast<FunctionProtoType>(F)) {
+ FunctionType::ExtInfo Info = getFunctionExtInfo(LHS);
+ QualType ResultType
+ = getFunctionType(OldReturnType, FPT->arg_type_begin(),
+ FPT->getNumArgs(), FPT->isVariadic(),
+ FPT->getTypeQuals(),
+ FPT->hasExceptionSpec(),
+ FPT->hasAnyExceptionSpec(),
+ FPT->getNumExceptions(),
+ FPT->exception_begin(),
+ Info);
+ return ResultType;
+ }
+ }
+ return QualType();
+ }
+
+ // If the qualifiers are different, the types can still be merged.
+ Qualifiers LQuals = LHSCan.getLocalQualifiers();
+ Qualifiers RQuals = RHSCan.getLocalQualifiers();
+ if (LQuals != RQuals) {
+ // If any of these qualifiers are different, we have a type mismatch.
+ if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
+ LQuals.getAddressSpace() != RQuals.getAddressSpace())
+ return QualType();
+
+ // Exactly one GC qualifier difference is allowed: __strong is
+ // okay if the other type has no GC qualifier but is an Objective
+ // C object pointer (i.e. implicitly strong by default). We fix
+ // this by pretending that the unqualified type was actually
+ // qualified __strong.
+ Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
+ Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
+ assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
+
+ if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
+ return QualType();
+
+ if (GC_L == Qualifiers::Strong)
+ return LHS;
+ if (GC_R == Qualifiers::Strong)
+ return RHS;
+ return QualType();
+ }
+
+ if (LHSCan->isObjCObjectPointerType() && RHSCan->isObjCObjectPointerType()) {
+ QualType LHSBaseQT = LHS->getAs<ObjCObjectPointerType>()->getPointeeType();
+ QualType RHSBaseQT = RHS->getAs<ObjCObjectPointerType>()->getPointeeType();
+ QualType ResQT = mergeObjCGCQualifiers(LHSBaseQT, RHSBaseQT);
+ if (ResQT == LHSBaseQT)
+ return LHS;
+ if (ResQT == RHSBaseQT)
+ return RHS;
+ }
+ return QualType();
+}
+
//===----------------------------------------------------------------------===//
// Integer Predicates
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud