summaryrefslogtreecommitdiffstats
path: root/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
committerdim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
commitc72c57c9e9b69944e3e009cd5e209634839581d3 (patch)
tree4fc2f184c499d106f29a386c452b49e5197bf63d /lib/AST/ASTContext.cpp
parent5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff)
downloadFreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip
FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r--lib/AST/ASTContext.cpp767
1 files changed, 523 insertions, 244 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 74c68ae..7245c03 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -12,28 +12,29 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
+#include "CXXABI.h"
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/Comment.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#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/ASTMutationListener.h"
-#include "clang/AST/RecordLayout.h"
#include "clang/AST/Mangle.h"
-#include "clang/AST/Comment.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Capacity.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Capacity.h"
-#include "CXXABI.h"
#include <map>
using namespace clang;
@@ -84,6 +85,14 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
return NULL;
}
+ if (const ClassTemplateSpecializationDecl *CTSD =
+ dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ TemplateSpecializationKind TSK = CTSD->getSpecializationKind();
+ if (TSK == TSK_ImplicitInstantiation ||
+ TSK == TSK_Undeclared)
+ return NULL;
+ }
+
if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return NULL;
@@ -364,10 +373,12 @@ static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod,
if (!ID)
return;
// Add redeclared method here.
- for (const ObjCCategoryDecl *ClsExtDecl = ID->getFirstClassExtension();
- ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
+ for (ObjCInterfaceDecl::known_extensions_iterator
+ Ext = ID->known_extensions_begin(),
+ ExtEnd = ID->known_extensions_end();
+ Ext != ExtEnd; ++Ext) {
if (ObjCMethodDecl *RedeclaredMethod =
- ClsExtDecl->getMethod(ObjCMethod->getSelector(),
+ Ext->getMethod(ObjCMethod->getSelector(),
ObjCMethod->isInstanceMethod()))
Redeclared.push_back(RedeclaredMethod);
}
@@ -412,15 +423,26 @@ comments::FullComment *ASTContext::getCommentForDecl(
if (!RC) {
if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
SmallVector<const NamedDecl*, 8> Overridden;
- if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
+ const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D);
+ if (OMD && OMD->isPropertyAccessor())
+ if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
+ if (comments::FullComment *FC = getCommentForDecl(PDecl, PP))
+ return cloneFullComment(FC, D);
+ if (OMD)
addRedeclaredMethods(OMD, Overridden);
getOverriddenMethods(dyn_cast<NamedDecl>(D), Overridden);
- for (unsigned i = 0, e = Overridden.size(); i < e; i++) {
- if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) {
- comments::FullComment *CFC = cloneFullComment(FC, D);
- return CFC;
- }
- }
+ for (unsigned i = 0, e = Overridden.size(); i < e; i++)
+ if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP))
+ return cloneFullComment(FC, D);
+ }
+ else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ // Attach any tag type's documentation to its typedef if latter
+ // does not have one of its own.
+ QualType QT = TD->getUnderlyingType();
+ if (const TagType *TT = QT->getAs<TagType>())
+ if (const Decl *TD = TT->getDecl())
+ if (comments::FullComment *FC = getCommentForDecl(TD, PP))
+ return cloneFullComment(FC, D);
}
return NULL;
}
@@ -571,12 +593,14 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
if (!LangOpts.CPlusPlus) return 0;
- switch (T.getCXXABI()) {
- case CXXABI_ARM:
+ switch (T.getCXXABI().getKind()) {
+ case TargetCXXABI::GenericARM:
+ case TargetCXXABI::iOS:
return CreateARMCXXABI(*this);
- case CXXABI_Itanium:
+ case TargetCXXABI::GenericAArch64: // Same as Itanium at this level
+ case TargetCXXABI::GenericItanium:
return CreateItaniumCXXABI(*this);
- case CXXABI_Microsoft:
+ case TargetCXXABI::Microsoft:
return CreateMicrosoftCXXABI(*this);
}
llvm_unreachable("Invalid CXXABI type!");
@@ -630,9 +654,9 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
DeclarationNames(*this),
ExternalSource(0), Listener(0),
Comments(SM), CommentsLoaded(false),
- CommentCommandTraits(BumpAlloc),
+ CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
LastSDM(0, 0),
- UniqueBlockByRefTypeID(0)
+ UniqueBlockByRefTypeID(0)
{
if (size_reserve > 0) Types.reserve(size_reserve);
TUDecl = TranslationUnitDecl::Create(*this);
@@ -873,12 +897,26 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
+
+ if (LangOpts.OpenCL) {
+ InitBuiltinType(OCLImage1dTy, BuiltinType::OCLImage1d);
+ InitBuiltinType(OCLImage1dArrayTy, BuiltinType::OCLImage1dArray);
+ InitBuiltinType(OCLImage1dBufferTy, BuiltinType::OCLImage1dBuffer);
+ InitBuiltinType(OCLImage2dTy, BuiltinType::OCLImage2d);
+ InitBuiltinType(OCLImage2dArrayTy, BuiltinType::OCLImage2dArray);
+ InitBuiltinType(OCLImage3dTy, BuiltinType::OCLImage3d);
+
+ InitBuiltinType(OCLSamplerTy, BuiltinType::OCLSampler);
+ InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent);
+ }
// Builtin type for __objc_yes and __objc_no
ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ?
SignedCharTy : BoolTy);
ObjCConstantStringType = QualType();
+
+ ObjCSuperType = QualType();
// void * type
VoidPtrTy = getPointerType(VoidTy);
@@ -1411,6 +1449,22 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
+ case BuiltinType::OCLSampler:
+ // Samplers are modeled as integers.
+ Width = Target->getIntWidth();
+ Align = Target->getIntAlign();
+ break;
+ case BuiltinType::OCLEvent:
+ case BuiltinType::OCLImage1d:
+ case BuiltinType::OCLImage1dArray:
+ case BuiltinType::OCLImage1dBuffer:
+ case BuiltinType::OCLImage2d:
+ case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage3d:
+ // Currently these types are pointers to opaque types.
+ Width = Target->getPointerWidth(0);
+ Align = Target->getPointerAlign(0);
+ break;
}
break;
case Type::ObjCObjectPointer:
@@ -1442,10 +1496,7 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
}
case Type::MemberPointer: {
const MemberPointerType *MPT = cast<MemberPointerType>(T);
- std::pair<uint64_t, unsigned> PtrDiffInfo =
- getTypeInfo(getPointerDiffType());
- Width = PtrDiffInfo.first * ABI->getMemberPointerSize(MPT);
- Align = PtrDiffInfo.second;
+ llvm::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT);
break;
}
case Type::Complex: {
@@ -1548,18 +1599,21 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
}
case Type::Atomic: {
+ // Start with the base type information.
std::pair<uint64_t, unsigned> Info
= getTypeInfo(cast<AtomicType>(T)->getValueType());
Width = Info.first;
Align = Info.second;
- if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth() &&
- llvm::isPowerOf2_64(Width)) {
- // We can potentially perform lock-free atomic operations for this
- // type; promote the alignment appropriately.
- // FIXME: We could potentially promote the width here as well...
- // is that worthwhile? (Non-struct atomic types generally have
- // power-of-two size anyway, but structs might not. Requires a bit
- // of implementation work to make sure we zero out the extra bits.)
+
+ // If the size of the type doesn't exceed the platform's max
+ // atomic promotion width, make the size and alignment more
+ // favorable to atomic operations:
+ if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth()) {
+ // Round the size up to a power of 2.
+ if (!llvm::isPowerOf2_64(Width))
+ Width = llvm::NextPowerOf2(Width);
+
+ // Set the alignment equal to the size.
Align = static_cast<unsigned>(Width);
}
}
@@ -1658,9 +1712,13 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
}
// Categories of this Interface.
- for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList();
- CDeclChain; CDeclChain = CDeclChain->getNextClassCategory())
- CollectInheritedProtocols(CDeclChain, Protocols);
+ for (ObjCInterfaceDecl::visible_categories_iterator
+ Cat = OI->visible_categories_begin(),
+ CatEnd = OI->visible_categories_end();
+ Cat != CatEnd; ++Cat) {
+ CollectInheritedProtocols(*Cat, Protocols);
+ }
+
if (ObjCInterfaceDecl *SD = OI->getSuperClass())
while (SD) {
CollectInheritedProtocols(SD, Protocols);
@@ -1690,10 +1748,13 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const {
unsigned count = 0;
// Count ivars declared in class extension.
- for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
- CDecl = CDecl->getNextClassExtension())
- count += CDecl->ivar_size();
-
+ for (ObjCInterfaceDecl::known_extensions_iterator
+ Ext = OI->known_extensions_begin(),
+ ExtEnd = OI->known_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ count += Ext->ivar_size();
+ }
+
// Count ivar defined in this class's implementation. This
// includes synthesized ivars.
if (ObjCImplementationDecl *ImplDecl = OI->getImplementation())
@@ -1750,12 +1811,16 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCImpls[CatD] = ImplD;
}
-ObjCInterfaceDecl *ASTContext::getObjContainingInterface(NamedDecl *ND) const {
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext()))
+const ObjCInterfaceDecl *ASTContext::getObjContainingInterface(
+ const NamedDecl *ND) const {
+ if (const ObjCInterfaceDecl *ID =
+ dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext()))
return ID;
- if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ND->getDeclContext()))
+ if (const ObjCCategoryDecl *CD =
+ dyn_cast<ObjCCategoryDecl>(ND->getDeclContext()))
return CD->getClassInterface();
- if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(ND->getDeclContext()))
+ if (const ObjCImplDecl *IMD =
+ dyn_cast<ObjCImplDecl>(ND->getDeclContext()))
return IMD->getClassInterface();
return 0;
@@ -1906,8 +1971,10 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T,
const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExtInfo = Info;
- Result = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
- FPT->getNumArgs(), EPI);
+ Result = getFunctionType(FPT->getResultType(),
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI);
}
return cast<FunctionType>(Result.getTypePtr());
@@ -2562,16 +2629,25 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy,
return QualType(New, 0);
}
+/// \brief Determine whether \p T is canonical as the result type of a function.
+static bool isCanonicalResultType(QualType T) {
+ return T.isCanonical() &&
+ (T.getObjCLifetime() == Qualifiers::OCL_None ||
+ T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone);
+}
+
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
QualType
-ASTContext::getFunctionType(QualType ResultTy,
- const QualType *ArgArray, unsigned NumArgs,
+ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
const FunctionProtoType::ExtProtoInfo &EPI) const {
+ size_t NumArgs = ArgArray.size();
+
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
- FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, *this);
+ FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI,
+ *this);
void *InsertPos = 0;
if (FunctionProtoType *FTP =
@@ -2580,7 +2656,7 @@ ASTContext::getFunctionType(QualType ResultTy,
// Determine whether the type being created is already canonical or not.
bool isCanonical =
- EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical() &&
+ EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) &&
!EPI.HasTrailingReturn;
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
if (!ArgArray[i].isCanonicalAsParam())
@@ -2606,9 +2682,15 @@ ASTContext::getFunctionType(QualType ResultTy,
CanonicalEPI.ExtInfo
= CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv));
- Canonical = getFunctionType(getCanonicalType(ResultTy),
- CanonicalArgs.data(), NumArgs,
- CanonicalEPI);
+ // Result types do not have ARC lifetime qualifiers.
+ QualType CanResultTy = getCanonicalType(ResultTy);
+ if (ResultTy.getQualifiers().hasObjCLifetime()) {
+ Qualifiers Qs = CanResultTy.getQualifiers();
+ Qs.removeObjCLifetime();
+ CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
+ }
+
+ Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI);
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
@@ -2641,7 +2723,7 @@ ASTContext::getFunctionType(QualType ResultTy,
FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment);
FunctionProtoType::ExtProtoInfo newEPI = EPI;
newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv);
- new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI);
+ new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI);
Types.push_back(FTP);
FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
@@ -2877,8 +2959,8 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
QualType TST = getTemplateSpecializationType(Name, Args, Underlying);
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
- TemplateSpecializationTypeLoc TL
- = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+ TemplateSpecializationTypeLoc TL =
+ DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>();
TL.setTemplateKeywordLoc(SourceLocation());
TL.setTemplateNameLoc(NameLoc);
TL.setLAngleLoc(Args.getLAngleLoc());
@@ -3154,7 +3236,7 @@ ASTContext::getDependentTemplateSpecializationType(
}
QualType ASTContext::getPackExpansionType(QualType Pattern,
- llvm::Optional<unsigned> NumExpansions) {
+ Optional<unsigned> NumExpansions) {
llvm::FoldingSetNodeID ID;
PackExpansionType::Profile(ID, Pattern, NumExpansions);
@@ -3528,6 +3610,14 @@ QualType ASTContext::getUnsignedWCharType() const {
return UnsignedIntTy;
}
+QualType ASTContext::getIntPtrType() const {
+ return getFromTargetType(Target->getIntPtrType());
+}
+
+QualType ASTContext::getUIntPtrType() const {
+ return getCorrespondingUnsignedType(getIntPtrType());
+}
+
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType ASTContext::getPointerDiffType() const {
@@ -3993,7 +4083,8 @@ ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const {
uint64_t ElementCount = 1;
do {
ElementCount *= CA->getSize().getZExtValue();
- CA = dyn_cast<ConstantArrayType>(CA->getElementType());
+ CA = dyn_cast_or_null<ConstantArrayType>(
+ CA->getElementType()->getAsArrayTypeUnsafe());
} while (CA);
return ElementCount;
}
@@ -4032,7 +4123,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
assert(Domain->isRealFloatingType() && "Unknown domain!");
switch (EltRank) {
- case HalfRank: llvm_unreachable("Half ranks are not valid here");
+ case HalfRank: return HalfTy;
case FloatRank: return FloatTy;
case DoubleRank: return DoubleTy;
case LongDoubleRank: return LongDoubleTy;
@@ -4159,8 +4250,8 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
// At this point, we should have a signed or unsigned integer type.
if (Promotable->isSignedIntegerType())
return IntTy;
- uint64_t PromotableSize = getTypeSize(Promotable);
- uint64_t IntSize = getTypeSize(IntTy);
+ uint64_t PromotableSize = getIntWidth(Promotable);
+ uint64_t IntSize = getIntWidth(IntTy);
assert(Promotable->isUnsignedIntegerType() && PromotableSize <= IntSize);
return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy;
}
@@ -4273,6 +4364,16 @@ QualType ASTContext::getCFConstantStringType() const {
return getTagDeclType(CFConstantStringTypeDecl);
}
+QualType ASTContext::getObjCSuperType() const {
+ if (ObjCSuperType.isNull()) {
+ RecordDecl *ObjCSuperTypeDecl =
+ CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("objc_super"));
+ TUDecl->addDecl(ObjCSuperTypeDecl);
+ ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl);
+ }
+ return ObjCSuperType;
+}
+
void ASTContext::setCFConstantStringType(QualType T) {
const RecordType *Rec = T->getAs<RecordType>();
assert(Rec && "Invalid CFConstantStringType");
@@ -4361,78 +4462,68 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
return getTagDeclType(BlockDescriptorExtendedType);
}
-bool ASTContext::BlockRequiresCopying(QualType Ty) const {
- if (Ty->isObjCRetainableType())
+/// BlockRequiresCopying - Returns true if byref variable "D" of type "Ty"
+/// requires copy/dispose. Note that this must match the logic
+/// in buildByrefHelpers.
+bool ASTContext::BlockRequiresCopying(QualType Ty,
+ const VarDecl *D) {
+ if (const CXXRecordDecl *record = Ty->getAsCXXRecordDecl()) {
+ const Expr *copyExpr = getBlockVarCopyInits(D);
+ if (!copyExpr && record->hasTrivialDestructor()) return false;
+
return true;
- if (getLangOpts().CPlusPlus) {
- if (const RecordType *RT = Ty->getAs<RecordType>()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- return RD->hasConstCopyConstructor();
-
+ }
+
+ if (!Ty->isObjCRetainableType()) return false;
+
+ Qualifiers qs = Ty.getQualifiers();
+
+ // If we have lifetime, that dominates.
+ if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
+ assert(getLangOpts().ObjCAutoRefCount);
+
+ switch (lifetime) {
+ case Qualifiers::OCL_None: llvm_unreachable("impossible");
+
+ // These are just bits as far as the runtime is concerned.
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ // Tell the runtime that this is ARC __weak, called by the
+ // byref routines.
+ case Qualifiers::OCL_Weak:
+ // ARC __strong __block variables need to be retained.
+ case Qualifiers::OCL_Strong:
+ return true;
}
+ llvm_unreachable("fell out of lifetime switch!");
}
- return false;
+ return (Ty->isBlockPointerType() || isObjCNSObjectType(Ty) ||
+ Ty->isObjCObjectPointerType());
}
-QualType
-ASTContext::BuildByRefType(StringRef DeclName, QualType Ty) const {
- // type = struct __Block_byref_1_X {
- // void *__isa;
- // struct __Block_byref_1_X *__forwarding;
- // unsigned int __flags;
- // unsigned int __size;
- // void *__copy_helper; // as needed
- // void *__destroy_help // as needed
- // int X;
- // } *
-
- bool HasCopyAndDispose = BlockRequiresCopying(Ty);
-
- // FIXME: Move up
- SmallString<36> Name;
- llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
- ++UniqueBlockByRefTypeID << '_' << DeclName;
- RecordDecl *T;
- T = CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get(Name.str()));
- T->startDefinition();
- QualType Int32Ty = IntTy;
- assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
- QualType FieldTypes[] = {
- getPointerType(VoidPtrTy),
- getPointerType(getTagDeclType(T)),
- Int32Ty,
- Int32Ty,
- getPointerType(VoidPtrTy),
- getPointerType(VoidPtrTy),
- Ty
- };
-
- StringRef FieldNames[] = {
- "__isa",
- "__forwarding",
- "__flags",
- "__size",
- "__copy_helper",
- "__destroy_helper",
- DeclName,
- };
-
- for (size_t i = 0; i < 7; ++i) {
- if (!HasCopyAndDispose && i >=4 && i <= 5)
- continue;
- FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
- SourceLocation(),
- &Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0, /*Mutable=*/false,
- ICIS_NoInit);
- Field->setAccess(AS_public);
- T->addDecl(Field);
- }
-
- T->completeDefinition();
-
- return getPointerType(getTagDeclType(T));
+bool ASTContext::getByrefLifetime(QualType Ty,
+ Qualifiers::ObjCLifetime &LifeTime,
+ bool &HasByrefExtendedLayout) const {
+
+ if (!getLangOpts().ObjC1 ||
+ getLangOpts().getGC() != LangOptions::NonGC)
+ return false;
+
+ HasByrefExtendedLayout = false;
+ if (Ty->isRecordType()) {
+ HasByrefExtendedLayout = true;
+ LifeTime = Qualifiers::OCL_None;
+ }
+ else if (getLangOpts().ObjCAutoRefCount)
+ LifeTime = Ty.getObjCLifetime();
+ // MRR.
+ else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType())
+ LifeTime = Qualifiers::OCL_ExplicitNone;
+ else
+ LifeTime = Qualifiers::OCL_None;
+ return true;
}
TypedefDecl *ASTContext::getObjCInstanceTypeDecl() {
@@ -4793,17 +4884,19 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
true /* outermost type */);
}
-static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) {
- switch (T->getAs<BuiltinType>()->getKind()) {
- default: llvm_unreachable("Unhandled builtin type kind");
+static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
+ BuiltinType::Kind kind) {
+ switch (kind) {
case BuiltinType::Void: return 'v';
case BuiltinType::Bool: return 'B';
case BuiltinType::Char_U:
case BuiltinType::UChar: return 'C';
+ case BuiltinType::Char16:
case BuiltinType::UShort: return 'S';
+ case BuiltinType::Char32:
case BuiltinType::UInt: return 'I';
case BuiltinType::ULong:
- return C->getIntWidth(T) == 32 ? 'L' : 'Q';
+ return C->getTargetInfo().getLongWidth() == 32 ? 'L' : 'Q';
case BuiltinType::UInt128: return 'T';
case BuiltinType::ULongLong: return 'Q';
case BuiltinType::Char_S:
@@ -4813,13 +4906,40 @@ static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) {
case BuiltinType::WChar_U:
case BuiltinType::Int: return 'i';
case BuiltinType::Long:
- return C->getIntWidth(T) == 32 ? 'l' : 'q';
+ return C->getTargetInfo().getLongWidth() == 32 ? 'l' : 'q';
case BuiltinType::LongLong: return 'q';
case BuiltinType::Int128: return 't';
case BuiltinType::Float: return 'f';
case BuiltinType::Double: return 'd';
case BuiltinType::LongDouble: return 'D';
+ case BuiltinType::NullPtr: return '*'; // like char*
+
+ case BuiltinType::Half:
+ // FIXME: potentially need @encodes for these!
+ return ' ';
+
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ llvm_unreachable("@encoding ObjC primitive type");
+
+ // OpenCL and placeholder types don't need @encodings.
+ case BuiltinType::OCLImage1d:
+ case BuiltinType::OCLImage1dArray:
+ case BuiltinType::OCLImage1dBuffer:
+ case BuiltinType::OCLImage2d:
+ case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage3d:
+ case BuiltinType::OCLEvent:
+ case BuiltinType::OCLSampler:
+ case BuiltinType::Dependent:
+#define BUILTIN_TYPE(KIND, ID)
+#define PLACEHOLDER_TYPE(KIND, ID) \
+ case BuiltinType::KIND:
+#include "clang/AST/BuiltinTypes.def"
+ llvm_unreachable("invalid builtin type for @encode");
}
+ llvm_unreachable("invalid BuiltinType::Kind value");
}
static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) {
@@ -4830,7 +4950,8 @@ static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) {
return 'i';
// The encoding of a fixed enum type matches its fixed underlying type.
- return ObjCEncodingForPrimitiveKind(C, Enum->getIntegerType());
+ const BuiltinType *BT = Enum->getIntegerType()->castAs<BuiltinType>();
+ return getObjCEncodingForPrimitiveKind(C, BT->getKind());
}
static void EncodeBitField(const ASTContext *Ctx, std::string& S,
@@ -4858,8 +4979,10 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S,
S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex()));
if (const EnumType *ET = T->getAs<EnumType>())
S += ObjCEncodingForEnumType(Ctx, ET);
- else
- S += ObjCEncodingForPrimitiveKind(Ctx, T);
+ else {
+ const BuiltinType *BT = T->castAs<BuiltinType>();
+ S += getObjCEncodingForPrimitiveKind(Ctx, BT->getKind());
+ }
}
S += llvm::utostr(FD->getBitWidthValue(*Ctx));
}
@@ -4873,33 +4996,52 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
bool EncodingProperty,
bool StructField,
bool EncodeBlockParameters,
- bool EncodeClassNames) const {
- if (T->getAs<BuiltinType>()) {
+ bool EncodeClassNames,
+ bool EncodePointerToObjCTypedef) const {
+ CanQualType CT = getCanonicalType(T);
+ switch (CT->getTypeClass()) {
+ case Type::Builtin:
+ case Type::Enum:
if (FD && FD->isBitField())
return EncodeBitField(this, S, T, FD);
- S += ObjCEncodingForPrimitiveKind(this, T);
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CT))
+ S += getObjCEncodingForPrimitiveKind(this, BT->getKind());
+ else
+ S += ObjCEncodingForEnumType(this, cast<EnumType>(CT));
return;
- }
- if (const ComplexType *CT = T->getAs<ComplexType>()) {
+ case Type::Complex: {
+ const ComplexType *CT = T->castAs<ComplexType>();
S += 'j';
getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false,
false);
return;
}
-
- // encoding for pointer or r3eference types.
- QualType PointeeTy;
- if (const PointerType *PT = T->getAs<PointerType>()) {
- if (PT->isObjCSelType()) {
- S += ':';
- return;
- }
- PointeeTy = PT->getPointeeType();
+
+ case Type::Atomic: {
+ const AtomicType *AT = T->castAs<AtomicType>();
+ S += 'A';
+ getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, 0,
+ false, false);
+ return;
}
- else if (const ReferenceType *RT = T->getAs<ReferenceType>())
- PointeeTy = RT->getPointeeType();
- if (!PointeeTy.isNull()) {
+
+ // encoding for pointer or reference types.
+ case Type::Pointer:
+ case Type::LValueReference:
+ case Type::RValueReference: {
+ QualType PointeeTy;
+ if (isa<PointerType>(CT)) {
+ const PointerType *PT = T->castAs<PointerType>();
+ if (PT->isObjCSelType()) {
+ S += ':';
+ return;
+ }
+ PointeeTy = PT->getPointeeType();
+ } else {
+ PointeeTy = T->castAs<ReferenceType>()->getPointeeType();
+ }
+
bool isReadOnly = false;
// For historical/compatibility reasons, the read-only qualifier of the
// pointee gets emitted _before_ the '^'. The read-only qualifier of
@@ -4954,10 +5096,12 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
NULL);
return;
}
-
- if (const ArrayType *AT =
- // Ignore type qualifiers etc.
- dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) {
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray: {
+ const ArrayType *AT = cast<ArrayType>(CT);
+
if (isa<IncompleteArrayType>(AT) && !StructField) {
// Incomplete arrays are encoded as a pointer to the array element.
S += '^';
@@ -4986,13 +5130,13 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
return;
}
- if (T->getAs<FunctionType>()) {
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
S += '?';
return;
- }
- if (const RecordType *RTy = T->getAs<RecordType>()) {
- RecordDecl *RDecl = RTy->getDecl();
+ case Type::Record: {
+ RecordDecl *RDecl = cast<RecordType>(CT)->getDecl();
S += RDecl->isUnion() ? '(' : '{';
// Anonymous structures print as '?'
if (const IdentifierInfo *II = RDecl->getIdentifier()) {
@@ -5000,13 +5144,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- std::string TemplateArgsStr
- = TemplateSpecializationType::PrintTemplateArgumentList(
+ llvm::raw_string_ostream OS(S);
+ TemplateSpecializationType::PrintTemplateArgumentList(OS,
TemplateArgs.data(),
TemplateArgs.size(),
(*this).getPrintingPolicy());
-
- S += TemplateArgsStr;
}
} else {
S += '?';
@@ -5043,19 +5185,12 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
S += RDecl->isUnion() ? ')' : '}';
return;
}
-
- if (const EnumType *ET = T->getAs<EnumType>()) {
- if (FD && FD->isBitField())
- EncodeBitField(this, S, T, FD);
- else
- S += ObjCEncodingForEnumType(this, ET);
- return;
- }
- if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
+ case Type::BlockPointer: {
+ const BlockPointerType *BT = T->castAs<BlockPointerType>();
S += "@?"; // Unlike a pointer-to-function, which is "^?".
if (EncodeBlockParameters) {
- const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
+ const FunctionType *FT = BT->getPointeeType()->castAs<FunctionType>();
S += '<';
// Block return type
@@ -5089,11 +5224,14 @@ 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();
+ case Type::ObjCObject:
+ case Type::ObjCInterface: {
+ // Ignore protocol qualifiers when mangling at this level.
+ T = T->castAs<ObjCObjectType>()->getBaseType();
- if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
+ // The assumption seems to be that this assert will succeed
+ // because nested levels will have filtered out 'id' and 'Class'.
+ const ObjCInterfaceType *OIT = T->castAs<ObjCInterfaceType>();
// @encode(class_name)
ObjCInterfaceDecl *OI = OIT->getDecl();
S += '{';
@@ -5107,13 +5245,16 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (Field->isBitField())
getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
else
- getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD);
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD,
+ false, false, false, false, false,
+ EncodePointerToObjCTypedef);
}
S += '}';
return;
}
- if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
+ case Type::ObjCObjectPointer: {
+ const ObjCObjectPointerType *OPT = T->castAs<ObjCObjectPointerType>();
if (OPT->isObjCIdType()) {
S += '@';
return;
@@ -5148,14 +5289,17 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
QualType PointeeTy = OPT->getPointeeType();
if (!EncodingProperty &&
- isa<TypedefType>(PointeeTy.getTypePtr())) {
+ isa<TypedefType>(PointeeTy.getTypePtr()) &&
+ !EncodePointerToObjCTypedef) {
// Another historical/compatibility reason.
// We encode the underlying type which comes out as
// {...};
S += '^';
getObjCEncodingForTypeImpl(PointeeTy, S,
false, ExpandPointedToStructures,
- NULL);
+ NULL,
+ false, false, false, false, false,
+ /*EncodePointerToObjCTypedef*/true);
return;
}
@@ -5176,18 +5320,29 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
// gcc just blithely ignores member pointers.
- // TODO: maybe there should be a mangling for these
- if (T->getAs<MemberPointerType>())
+ // FIXME: we shoul do better than that. 'M' is available.
+ case Type::MemberPointer:
return;
- if (T->isVectorType()) {
+ case Type::Vector:
+ case Type::ExtVector:
// This matches gcc's encoding, even though technically it is
// insufficient.
// FIXME. We should do a better job than gcc.
return;
+
+#define ABSTRACT_TYPE(KIND, BASE)
+#define TYPE(KIND, BASE)
+#define DEPENDENT_TYPE(KIND, BASE) \
+ case Type::KIND:
+#define NON_CANONICAL_TYPE(KIND, BASE) \
+ case Type::KIND:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(KIND, BASE) \
+ case Type::KIND:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("@encode for dependent type!");
}
-
- llvm_unreachable("@encode for type not implemented!");
+ llvm_unreachable("bad type kind!");
}
void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
@@ -5426,6 +5581,85 @@ static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) {
return VaListTypeDecl;
}
+static TypedefDecl *
+CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) {
+ RecordDecl *VaListTagDecl;
+ if (Context->getLangOpts().CPlusPlus) {
+ // namespace std { struct __va_list {
+ NamespaceDecl *NS;
+ NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
+ Context->getTranslationUnitDecl(),
+ /*Inline*/false, SourceLocation(),
+ SourceLocation(), &Context->Idents.get("std"),
+ /*PrevDecl*/0);
+
+ VaListTagDecl = CXXRecordDecl::Create(*Context, TTK_Struct,
+ Context->getTranslationUnitDecl(),
+ SourceLocation(), SourceLocation(),
+ &Context->Idents.get("__va_list"));
+ VaListTagDecl->setDeclContext(NS);
+ } else {
+ // struct __va_list
+ VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct,
+ Context->getTranslationUnitDecl(),
+ &Context->Idents.get("__va_list"));
+ }
+
+ VaListTagDecl->startDefinition();
+
+ const size_t NumFields = 5;
+ QualType FieldTypes[NumFields];
+ const char *FieldNames[NumFields];
+
+ // void *__stack;
+ FieldTypes[0] = Context->getPointerType(Context->VoidTy);
+ FieldNames[0] = "__stack";
+
+ // void *__gr_top;
+ FieldTypes[1] = Context->getPointerType(Context->VoidTy);
+ FieldNames[1] = "__gr_top";
+
+ // void *__vr_top;
+ FieldTypes[2] = Context->getPointerType(Context->VoidTy);
+ FieldNames[2] = "__vr_top";
+
+ // int __gr_offs;
+ FieldTypes[3] = Context->IntTy;
+ FieldNames[3] = "__gr_offs";
+
+ // int __vr_offs;
+ FieldTypes[4] = Context->IntTy;
+ FieldNames[4] = "__vr_offs";
+
+ // Create fields
+ for (unsigned i = 0; i < NumFields; ++i) {
+ FieldDecl *Field = FieldDecl::Create(const_cast<ASTContext &>(*Context),
+ VaListTagDecl,
+ SourceLocation(),
+ SourceLocation(),
+ &Context->Idents.get(FieldNames[i]),
+ FieldTypes[i], /*TInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false,
+ ICIS_NoInit);
+ Field->setAccess(AS_public);
+ VaListTagDecl->addDecl(Field);
+ }
+ VaListTagDecl->completeDefinition();
+ QualType VaListTagType = Context->getRecordType(VaListTagDecl);
+ Context->VaListTagTy = VaListTagType;
+
+ // } __builtin_va_list;
+ TypedefDecl *VaListTypedefDecl
+ = TypedefDecl::Create(const_cast<ASTContext &>(*Context),
+ Context->getTranslationUnitDecl(),
+ SourceLocation(), SourceLocation(),
+ &Context->Idents.get("__builtin_va_list"),
+ Context->getTrivialTypeSourceInfo(VaListTagType));
+
+ return VaListTypedefDecl;
+}
+
static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) {
// typedef struct __va_list_tag {
RecordDecl *VaListTagDecl;
@@ -5659,6 +5893,8 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context,
return CreateCharPtrBuiltinVaListDecl(Context);
case TargetInfo::VoidPtrBuiltinVaList:
return CreateVoidPtrBuiltinVaListDecl(Context);
+ case TargetInfo::AArch64ABIBuiltinVaList:
+ return CreateAArch64ABIBuiltinVaListDecl(Context);
case TargetInfo::PowerABIBuiltinVaList:
return CreatePowerABIBuiltinVaListDecl(Context);
case TargetInfo::X86_64ABIBuiltinVaList:
@@ -6496,14 +6732,14 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult())
return QualType();
- // functypes which return are preferred over those that do not.
- if (lbaseInfo.getNoReturn() && !rbaseInfo.getNoReturn())
- allLTypes = false;
- else if (!lbaseInfo.getNoReturn() && rbaseInfo.getNoReturn())
- allRTypes = false;
// FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
+ if (lbaseInfo.getNoReturn() != NoReturn)
+ allLTypes = false;
+ if (rbaseInfo.getNoReturn() != NoReturn)
+ allRTypes = false;
+
FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn);
if (lproto && rproto) { // two C99 style function prototypes
@@ -6557,7 +6793,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo();
EPI.ExtInfo = einfo;
- return getFunctionType(retType, types.begin(), types.size(), EPI);
+ return getFunctionType(retType, types, EPI);
}
if (lproto) allRTypes = false;
@@ -6594,8 +6830,10 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo();
EPI.ExtInfo = einfo;
- return getFunctionType(retType, proto->arg_type_begin(),
- proto->getNumArgs(), EPI);
+ return getFunctionType(retType,
+ ArrayRef<QualType>(proto->arg_type_begin(),
+ proto->getNumArgs()),
+ EPI);
}
if (allLTypes) return lhs;
@@ -6603,6 +6841,27 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
return getFunctionNoProtoType(retType, einfo);
}
+/// Given that we have an enum type and a non-enum type, try to merge them.
+static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET,
+ QualType other, bool isBlockReturnType) {
+ // C99 6.7.2.2p4: Each enumerated type shall be compatible with char,
+ // a signed integer type, or an unsigned integer type.
+ // Compatibility is based on the underlying type, not the promotion
+ // type.
+ QualType underlyingType = ET->getDecl()->getIntegerType();
+ if (underlyingType.isNull()) return QualType();
+ if (Context.hasSameType(underlyingType, other))
+ return other;
+
+ // In block return types, we're more permissive and accept any
+ // integral type of the same size.
+ if (isBlockReturnType && other->isIntegerType() &&
+ Context.getTypeSize(underlyingType) == Context.getTypeSize(other))
+ return other;
+
+ return QualType();
+}
+
QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
bool OfBlockPointer,
bool Unqualified, bool BlockReturnType) {
@@ -6684,19 +6943,13 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// If the canonical type classes don't match.
if (LHSClass != RHSClass) {
- // C99 6.7.2.2p4: Each enumerated type shall be compatible with char,
- // a signed integer type, or an unsigned integer type.
- // Compatibility is based on the underlying type, not the promotion
- // type.
+ // Note that we only have special rules for turning block enum
+ // returns into block int returns, not vice-versa.
if (const EnumType* ETy = LHS->getAs<EnumType>()) {
- QualType TINT = ETy->getDecl()->getIntegerType();
- if (!TINT.isNull() && hasSameType(TINT, RHSCan.getUnqualifiedType()))
- return RHS;
+ return mergeEnumWithInteger(*this, ETy, RHS, false);
}
if (const EnumType* ETy = RHS->getAs<EnumType>()) {
- QualType TINT = ETy->getDecl()->getIntegerType();
- if (!TINT.isNull() && hasSameType(TINT, LHSCan.getUnqualifiedType()))
- return LHS;
+ return mergeEnumWithInteger(*this, ETy, LHS, BlockReturnType);
}
// allow block pointer type to match an 'id' type.
if (OfBlockPointer && !BlockReturnType) {
@@ -6928,8 +7181,10 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExtInfo = getFunctionExtInfo(LHS);
QualType ResultType
- = getFunctionType(OldReturnType, FPT->arg_type_begin(),
- FPT->getNumArgs(), EPI);
+ = getFunctionType(OldReturnType,
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI);
return ResultType;
}
}
@@ -7137,6 +7392,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
case 'H':
Type = Context.getObjCSelType();
break;
+ case 'M':
+ Type = Context.getObjCSuperType();
+ break;
case 'a':
Type = Context.getBuiltinVaListType();
assert(!Type.isNull() && "builtin va list type not initialized!");
@@ -7318,7 +7576,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
EPI.ExtInfo = EI;
EPI.Variadic = Variadic;
- return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), EPI);
+ return getFunctionType(ResType, ArgTypes, EPI);
}
GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
@@ -7383,9 +7641,6 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
TSK = VD->getTemplateSpecializationKind();
Linkage L = VD->getLinkage();
- if (L == ExternalLinkage && getLangOpts().CPlusPlus &&
- VD->getType()->getLinkage() == UniqueExternalLinkage)
- L = UniqueExternalLinkage;
switch (L) {
case NoLinkage:
@@ -7418,7 +7673,15 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (!VD->isFileVarDecl())
return false;
- } else if (!isa<FunctionDecl>(D))
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // We never need to emit an uninstantiated function template.
+ if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
+ return false;
+ } else
+ return false;
+
+ // If this is a member of a class template, we do not need to emit it.
+ if (D->getDeclContext()->isDependentContext())
return false;
// Weak references don't produce any output by themselves.
@@ -7438,13 +7701,16 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
return true;
- // The key function for a class is required.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- const CXXRecordDecl *RD = MD->getParent();
- if (MD->isOutOfLine() && RD->isDynamicClass()) {
- const CXXMethodDecl *KeyFunc = getKeyFunction(RD);
- if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl())
- return true;
+ // The key function for a class is required. This rule only comes
+ // into play when inline functions can be key functions, though.
+ if (getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXRecordDecl *RD = MD->getParent();
+ if (MD->isOutOfLine() && RD->isDynamicClass()) {
+ const CXXMethodDecl *KeyFunc = getCurrentKeyFunction(RD);
+ if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl())
+ return true;
+ }
}
}
@@ -7465,27 +7731,20 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly)
return false;
- // Structs that have non-trivial constructors or destructors are required.
+ // Variables that can be needed in other TUs are required.
+ GVALinkage L = GetGVALinkageForVariable(VD);
+ if (L != GVA_Internal && L != GVA_TemplateInstantiation)
+ return true;
- // FIXME: Handle references.
- // FIXME: Be more selective about which constructors we care about.
- if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- if (RD->hasDefinition() && !(RD->hasTrivialDefaultConstructor() &&
- RD->hasTrivialCopyConstructor() &&
- RD->hasTrivialMoveConstructor() &&
- RD->hasTrivialDestructor()))
- return true;
- }
- }
+ // Variables that have destruction with side-effects are required.
+ if (VD->getType().isDestructedType())
+ return true;
- GVALinkage L = GetGVALinkageForVariable(VD);
- if (L == GVA_Internal || L == GVA_TemplateInstantiation) {
- if (!(VD->getInit() && VD->getInit()->HasSideEffects(*this)))
- return false;
- }
+ // Variables that have initialization with side-effects are required.
+ if (VD->getInit() && VD->getInit()->HasSideEffects(*this))
+ return true;
- return true;
+ return false;
}
CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) {
@@ -7494,7 +7753,8 @@ CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) {
}
CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const {
- if (CC == CC_C && !LangOpts.MRTD && getTargetInfo().getCXXABI() != CXXABI_Microsoft)
+ if (CC == CC_C && !LangOpts.MRTD &&
+ getTargetInfo().getCXXABI().isMemberFunctionCCDefault())
return CC_Default;
return CC;
}
@@ -7505,11 +7765,13 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
}
MangleContext *ASTContext::createMangleContext() {
- switch (Target->getCXXABI()) {
- case CXXABI_ARM:
- case CXXABI_Itanium:
+ switch (Target->getCXXABI().getKind()) {
+ case TargetCXXABI::GenericAArch64:
+ case TargetCXXABI::GenericItanium:
+ case TargetCXXABI::GenericARM:
+ case TargetCXXABI::iOS:
return createItaniumMangleContext(*this, getDiagnostics());
- case CXXABI_Microsoft:
+ case TargetCXXABI::Microsoft:
return createMicrosoftMangleContext(*this, getDiagnostics());
}
llvm_unreachable("Unsupported ABI");
@@ -7534,6 +7796,23 @@ size_t ASTContext::getSideTableAllocatedMemory() const {
+ llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
}
+void ASTContext::addUnnamedTag(const TagDecl *Tag) {
+ // FIXME: This mangling should be applied to function local classes too
+ if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() ||
+ !isa<CXXRecordDecl>(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage)
+ return;
+
+ std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P =
+ UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0));
+ UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++));
+}
+
+int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const {
+ llvm::DenseMap<const TagDecl *, unsigned>::const_iterator I =
+ UnnamedMangleNumbers.find(Tag);
+ return I != UnnamedMangleNumbers.end() ? I->second : -1;
+}
+
unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) {
CXXRecordDecl *Lambda = CallOperator->getParent();
return LambdaMangleContexts[Lambda->getDeclContext()]
OpenPOWER on IntegriCloud