aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTContext.cpp293
-rw-r--r--lib/AST/ASTDiagnostic.cpp74
-rw-r--r--lib/AST/ASTImporter.cpp20
-rw-r--r--lib/AST/Decl.cpp110
-rw-r--r--lib/AST/DeclBase.cpp35
-rw-r--r--lib/AST/DeclCXX.cpp54
-rw-r--r--lib/AST/DeclObjC.cpp58
-rw-r--r--lib/AST/DeclPrinter.cpp5
-rw-r--r--lib/AST/DeclarationName.cpp22
-rw-r--r--lib/AST/Expr.cpp256
-rw-r--r--lib/AST/ExprCXX.cpp60
-rw-r--r--lib/AST/ExprClassification.cpp15
-rw-r--r--lib/AST/ExprConstant.cpp68
-rw-r--r--lib/AST/ExternalASTSource.cpp4
-rw-r--r--lib/AST/ItaniumMangle.cpp447
-rw-r--r--lib/AST/NestedNameSpecifier.cpp22
-rw-r--r--lib/AST/ParentMap.cpp9
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp9
-rw-r--r--lib/AST/Stmt.cpp33
-rw-r--r--lib/AST/StmtPrinter.cpp26
-rw-r--r--lib/AST/StmtProfile.cpp308
-rw-r--r--lib/AST/TemplateBase.cpp43
-rw-r--r--lib/AST/TemplateName.cpp40
-rw-r--r--lib/AST/Type.cpp547
-rw-r--r--lib/AST/TypePrinter.cpp117
25 files changed, 2000 insertions, 675 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 9094abad2ef1..6eada6e22f4e 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -219,11 +219,12 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
FunctionProtoTypes(this_()),
TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()),
+ SubstTemplateTemplateParmPacks(this_()),
GlobalNestedNameSpecifier(0), IsInt128Installed(false),
CFConstantStringTypeDecl(0), NSConstantStringTypeDecl(0),
- ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
- sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
- cudaConfigureCallDecl(0),
+ ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0),
+ jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0),
+ BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0),
NullTypeSourceInfo(QualType()),
SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)),
AddrSpaceMap(getAddressSpaceMap(t, LOpts)), Target(t),
@@ -288,8 +289,8 @@ ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) {
}
void ASTContext::PrintStats() const {
- fprintf(stderr, "*** AST Context Stats:\n");
- fprintf(stderr, " %d types total.\n", (int)Types.size());
+ llvm::errs() << "\n*** AST Context Stats:\n";
+ llvm::errs() << " " << Types.size() << " types total.\n";
unsigned counts[] = {
#define TYPE(Name, Parent) 0,
@@ -307,40 +308,42 @@ void ASTContext::PrintStats() const {
unsigned TotalBytes = 0;
#define TYPE(Name, Parent) \
if (counts[Idx]) \
- fprintf(stderr, " %d %s types\n", (int)counts[Idx], #Name); \
+ llvm::errs() << " " << counts[Idx] << " " << #Name \
+ << " types\n"; \
TotalBytes += counts[Idx] * sizeof(Name##Type); \
++Idx;
#define ABSTRACT_TYPE(Name, Parent)
#include "clang/AST/TypeNodes.def"
- fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));
-
+ llvm::errs() << "Total bytes = " << TotalBytes << "\n";
+
// Implicit special member functions.
- fprintf(stderr, " %u/%u implicit default constructors created\n",
- NumImplicitDefaultConstructorsDeclared,
- NumImplicitDefaultConstructors);
- fprintf(stderr, " %u/%u implicit copy constructors created\n",
- NumImplicitCopyConstructorsDeclared,
- NumImplicitCopyConstructors);
+ llvm::errs() << NumImplicitDefaultConstructorsDeclared << "/"
+ << NumImplicitDefaultConstructors
+ << " implicit default constructors created\n";
+ llvm::errs() << NumImplicitCopyConstructorsDeclared << "/"
+ << NumImplicitCopyConstructors
+ << " implicit copy constructors created\n";
if (getLangOptions().CPlusPlus)
- fprintf(stderr, " %u/%u implicit move constructors created\n",
- NumImplicitMoveConstructorsDeclared,
- NumImplicitMoveConstructors);
- fprintf(stderr, " %u/%u implicit copy assignment operators created\n",
- NumImplicitCopyAssignmentOperatorsDeclared,
- NumImplicitCopyAssignmentOperators);
+ llvm::errs() << NumImplicitMoveConstructorsDeclared << "/"
+ << NumImplicitMoveConstructors
+ << " implicit move constructors created\n";
+ llvm::errs() << NumImplicitCopyAssignmentOperatorsDeclared << "/"
+ << NumImplicitCopyAssignmentOperators
+ << " implicit copy assignment operators created\n";
if (getLangOptions().CPlusPlus)
- fprintf(stderr, " %u/%u implicit move assignment operators created\n",
- NumImplicitMoveAssignmentOperatorsDeclared,
- NumImplicitMoveAssignmentOperators);
- fprintf(stderr, " %u/%u implicit destructors created\n",
- NumImplicitDestructorsDeclared, NumImplicitDestructors);
-
+ llvm::errs() << NumImplicitMoveAssignmentOperatorsDeclared << "/"
+ << NumImplicitMoveAssignmentOperators
+ << " implicit move assignment operators created\n";
+ llvm::errs() << NumImplicitDestructorsDeclared << "/"
+ << NumImplicitDestructors
+ << " implicit destructors created\n";
+
if (ExternalSource.get()) {
- fprintf(stderr, "\n");
+ llvm::errs() << "\n";
ExternalSource->PrintStats();
}
-
+
BumpAlloc.PrintStats();
}
@@ -753,7 +756,7 @@ ASTContext::getTypeInfo(const Type *T) const {
#define NON_CANONICAL_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
- assert(false && "Should not see dependent types");
+ llvm_unreachable("Should not see dependent types");
break;
case Type::FunctionNoProto:
@@ -1089,8 +1092,12 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
E = OI->ivar_end(); I != E; ++I)
Ivars.push_back(*I);
}
- else
- ShallowCollectObjCIvars(OI, Ivars);
+ else {
+ ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
+ for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
+ Iv= Iv->getNextIvar())
+ Ivars.push_back(Iv);
+ }
}
/// CollectInheritedProtocols - Collect all protocols in current class and
@@ -1881,7 +1888,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
/// the specified element type and size. VectorType must be a built-in type.
QualType
ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const {
- assert(vecType->isBuiltinType());
+ assert(vecType->isBuiltinType() || vecType->isDependentType());
// Check if we've already instantiated a vector of this type.
llvm::FoldingSetNodeID ID;
@@ -2040,10 +2047,13 @@ ASTContext::getFunctionType(QualType ResultTy,
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
}
- // FunctionProtoType objects are allocated with extra bytes after them
- // for two variable size arrays (for parameter and exception types) at the
- // end of them. Instead of the exception types, there could be a noexcept
- // expression and a context pointer.
+ // FunctionProtoType objects are allocated with extra bytes after
+ // them for three variable size arrays at the end:
+ // - parameter types
+ // - exception types
+ // - consumed-arguments flags
+ // Instead of the exception types, there could be a noexcept
+ // expression.
size_t Size = sizeof(FunctionProtoType) +
NumArgs * sizeof(QualType);
if (EPI.ExceptionSpecType == EST_Dynamic)
@@ -2051,6 +2061,9 @@ ASTContext::getFunctionType(QualType ResultTy,
else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
Size += sizeof(Expr*);
}
+ if (EPI.ConsumedArguments)
+ Size += NumArgs * sizeof(bool);
+
FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment);
FunctionProtoType::ExtProtoInfo newEPI = EPI;
newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv);
@@ -2791,7 +2804,12 @@ static QualType getDecltypeForExpr(const Expr *e, const ASTContext &Context) {
/// on canonical type's (which are always unique).
QualType ASTContext::getDecltypeType(Expr *e) const {
DecltypeType *dt;
- if (e->isTypeDependent()) {
+
+ // C++0x [temp.type]p2:
+ // If an expression e involves a template parameter, decltype(e) denotes a
+ // unique dependent type. Two such decltype-specifiers refer to the same
+ // type only if their expressions are equivalent (14.5.6.1).
+ if (e->isInstantiationDependent()) {
llvm::FoldingSetNodeID ID;
DependentDecltypeType::Profile(ID, *this, e);
@@ -2925,7 +2943,6 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) const {
return CanQualType::CreateUnsafe(Result);
}
-
QualType ASTContext::getUnqualifiedArrayType(QualType type,
Qualifiers &quals) {
SplitQualType splitType = type.getSplitUnqualifiedType();
@@ -3027,11 +3044,21 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
DeclarationNameInfo
ASTContext::getNameForTemplate(TemplateName Name,
SourceLocation NameLoc) const {
- if (TemplateDecl *TD = Name.getAsTemplateDecl())
+ switch (Name.getKind()) {
+ case TemplateName::QualifiedTemplate:
+ case TemplateName::Template:
// DNInfo work in progress: CHECKME: what about DNLoc?
- return DeclarationNameInfo(TD->getDeclName(), NameLoc);
+ return DeclarationNameInfo(Name.getAsTemplateDecl()->getDeclName(),
+ NameLoc);
- if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+ case TemplateName::OverloadedTemplate: {
+ OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate();
+ // DNInfo work in progress: CHECKME: what about DNLoc?
+ return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc);
+ }
+
+ case TemplateName::DependentTemplate: {
+ DependentTemplateName *DTN = Name.getAsDependentTemplateName();
DeclarationName DName;
if (DTN->isIdentifier()) {
DName = DeclarationNames.getIdentifier(DTN->getIdentifier());
@@ -3046,36 +3073,64 @@ ASTContext::getNameForTemplate(TemplateName Name,
}
}
- OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate();
- assert(Storage);
- // DNInfo work in progress: CHECKME: what about DNLoc?
- return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc);
+ case TemplateName::SubstTemplateTemplateParm: {
+ SubstTemplateTemplateParmStorage *subst
+ = Name.getAsSubstTemplateTemplateParm();
+ return DeclarationNameInfo(subst->getParameter()->getDeclName(),
+ NameLoc);
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ SubstTemplateTemplateParmPackStorage *subst
+ = Name.getAsSubstTemplateTemplateParmPack();
+ return DeclarationNameInfo(subst->getParameterPack()->getDeclName(),
+ NameLoc);
+ }
+ }
+
+ llvm_unreachable("bad template name kind!");
}
TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const {
- if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ switch (Name.getKind()) {
+ case TemplateName::QualifiedTemplate:
+ case TemplateName::Template: {
+ TemplateDecl *Template = Name.getAsTemplateDecl();
if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(Template))
+ = dyn_cast<TemplateTemplateParmDecl>(Template))
Template = getCanonicalTemplateTemplateParmDecl(TTP);
// The canonical template name is the canonical template declaration.
return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl()));
}
- if (SubstTemplateTemplateParmPackStorage *SubstPack
- = Name.getAsSubstTemplateTemplateParmPack()) {
- TemplateTemplateParmDecl *CanonParam
- = getCanonicalTemplateTemplateParmDecl(SubstPack->getParameterPack());
- TemplateArgument CanonArgPack
- = getCanonicalTemplateArgument(SubstPack->getArgumentPack());
- return getSubstTemplateTemplateParmPack(CanonParam, CanonArgPack);
+ case TemplateName::OverloadedTemplate:
+ llvm_unreachable("cannot canonicalize overloaded template");
+
+ case TemplateName::DependentTemplate: {
+ DependentTemplateName *DTN = Name.getAsDependentTemplateName();
+ assert(DTN && "Non-dependent template names must refer to template decls.");
+ return DTN->CanonicalTemplateName;
+ }
+
+ case TemplateName::SubstTemplateTemplateParm: {
+ SubstTemplateTemplateParmStorage *subst
+ = Name.getAsSubstTemplateTemplateParm();
+ return getCanonicalTemplateName(subst->getReplacement());
}
-
- assert(!Name.getAsOverloadedTemplate());
- DependentTemplateName *DTN = Name.getAsDependentTemplateName();
- assert(DTN && "Non-dependent template names must refer to template decls.");
- return DTN->CanonicalTemplateName;
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ SubstTemplateTemplateParmPackStorage *subst
+ = Name.getAsSubstTemplateTemplateParmPack();
+ TemplateTemplateParmDecl *canonParameter
+ = getCanonicalTemplateTemplateParmDecl(subst->getParameterPack());
+ TemplateArgument canonArgPack
+ = getCanonicalTemplateArgument(subst->getArgumentPack());
+ return getSubstTemplateTemplateParmPack(canonParameter, canonArgPack);
+ }
+ }
+
+ llvm_unreachable("bad template name!");
}
bool ASTContext::hasSameTemplateName(TemplateName X, TemplateName Y) {
@@ -3260,6 +3315,31 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
VAT->getBracketsRange()));
}
+QualType ASTContext::getAdjustedParameterType(QualType T) {
+ // C99 6.7.5.3p7:
+ // A declaration of a parameter as "array of type" shall be
+ // adjusted to "qualified pointer to type", where the type
+ // qualifiers (if any) are those specified within the [ and ] of
+ // the array type derivation.
+ if (T->isArrayType())
+ return getArrayDecayedType(T);
+
+ // C99 6.7.5.3p8:
+ // A declaration of a parameter as "function returning type"
+ // shall be adjusted to "pointer to function returning type", as
+ // in 6.3.2.1.
+ if (T->isFunctionType())
+ return getPointerType(T);
+
+ return T;
+}
+
+QualType ASTContext::getSignatureParameterType(QualType T) {
+ T = getVariableArrayDecayedType(T);
+ T = getAdjustedParameterType(T);
+ return T.getUnqualifiedType();
+}
+
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
/// handling typedefs etc. The canonical type of "T" must be an array type,
@@ -3459,6 +3539,25 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy;
}
+/// \brief Recurses in pointer/array types until it finds an objc retainable
+/// type and returns its ownership.
+Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const {
+ while (!T.isNull()) {
+ if (T.getObjCLifetime() != Qualifiers::OCL_None)
+ return T.getObjCLifetime();
+ if (T->isArrayType())
+ T = getBaseElementType(T);
+ else if (const PointerType *PT = T->getAs<PointerType>())
+ T = PT->getPointeeType();
+ else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ T = RT->getPointeeType();
+ else
+ break;
+ }
+
+ return Qualifiers::OCL_None;
+}
+
/// getIntegerTypeOrder - Returns the highest ranked integer type:
/// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If
/// LHS < RHS, return -1.
@@ -3725,11 +3824,7 @@ void ASTContext::setBlockDescriptorExtendedType(QualType T) {
}
bool ASTContext::BlockRequiresCopying(QualType Ty) const {
- if (Ty->isBlockPointerType())
- return true;
- if (isObjCNSObjectType(Ty))
- return true;
- if (Ty->isObjCObjectPointerType())
+ if (Ty->isObjCRetainableType())
return true;
if (getLangOptions().CPlusPlus) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -4180,17 +4275,7 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S,
if (!Ctx->getLangOptions().NeXTRuntime) {
const RecordDecl *RD = FD->getParent();
const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
- // FIXME: This same linear search is also used in ExprConstant - it might
- // be better if the FieldDecl stored its offset. We'd be increasing the
- // size of the object slightly, but saving some time every time it is used.
- unsigned i = 0;
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end();
- Field != FieldEnd; (void)++Field, ++i) {
- if (*Field == FD)
- break;
- }
- S += llvm::utostr(RL.getFieldOffset(i));
+ S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex()));
if (T->isEnumeralType())
S += 'i';
else
@@ -4510,6 +4595,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
BE = CXXRec->bases_end(); BI != BE; ++BI) {
if (!BI->isVirtual()) {
CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl();
+ if (base->isEmpty())
+ continue;
uint64_t offs = layout.getBaseClassOffsetInBits(base);
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
std::make_pair(offs, base));
@@ -4531,6 +4618,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
BI = CXXRec->vbases_begin(),
BE = CXXRec->vbases_end(); BI != BE; ++BI) {
CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl();
+ if (base->isEmpty())
+ continue;
uint64_t offs = layout.getVBaseClassOffsetInBits(base);
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
std::make_pair(offs, base));
@@ -4594,8 +4683,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
// expands virtual bases each time one is encountered in the hierarchy,
// making the encoding type bigger than it really is.
getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false);
- if (!base->isEmpty())
- CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize());
+ assert(!base->isEmpty());
+ CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize());
} else {
FieldDecl *field = cast<FieldDecl>(dcl);
if (FD) {
@@ -4782,6 +4871,24 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
}
TemplateName
+ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
+ TemplateName replacement) const {
+ llvm::FoldingSetNodeID ID;
+ SubstTemplateTemplateParmStorage::Profile(ID, param, replacement);
+
+ void *insertPos = 0;
+ SubstTemplateTemplateParmStorage *subst
+ = SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos);
+
+ if (!subst) {
+ subst = new (*this) SubstTemplateTemplateParmStorage(param, replacement);
+ SubstTemplateTemplateParms.InsertNode(subst, insertPos);
+ }
+
+ return TemplateName(subst);
+}
+
+TemplateName
ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
const TemplateArgument &ArgPack) const {
ASTContext &Self = const_cast<ASTContext &>(*this);
@@ -4793,7 +4900,7 @@ ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
= SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos);
if (!Subst) {
- Subst = new (*this) SubstTemplateTemplateParmPackStorage(Self, Param,
+ Subst = new (*this) SubstTemplateTemplateParmPackStorage(Param,
ArgPack.pack_size(),
ArgPack.pack_begin());
SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos);
@@ -4826,20 +4933,6 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const {
// Type Predicates.
//===----------------------------------------------------------------------===//
-/// isObjCNSObjectType - Return true if this is an NSObject object using
-/// NSObject attribute on a c-style pointer type.
-/// FIXME - Make it work directly on types.
-/// FIXME: Move to Type.
-///
-bool ASTContext::isObjCNSObjectType(QualType Ty) const {
- if (const TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
- if (TypedefNameDecl *TD = TDT->getDecl())
- if (TD->getAttr<ObjCNSObjectAttr>())
- return true;
- }
- return false;
-}
-
/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
/// garbage collection attribute.
///
@@ -5348,6 +5441,10 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
}
+bool ASTContext::propertyTypesAreCompatible(QualType LHS, QualType RHS) {
+ return typesAreCompatible(LHS, RHS);
+}
+
bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) {
return !mergeTypes(LHS, RHS, true).isNull();
}
@@ -5452,6 +5549,9 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm())
return QualType();
+ if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult())
+ return QualType();
+
// It's noreturn if either type is.
// FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
@@ -5460,10 +5560,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (NoReturn != rbaseInfo.getNoReturn())
allRTypes = false;
- FunctionType::ExtInfo einfo(NoReturn,
- lbaseInfo.getHasRegParm(),
- lbaseInfo.getRegParm(),
- lbaseInfo.getCC());
+ FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn);
if (lproto && rproto) { // two C99 style function prototypes
assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
@@ -5584,7 +5681,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// If any of these qualifiers are different, we have a type
// mismatch.
if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
- LQuals.getAddressSpace() != RQuals.getAddressSpace())
+ LQuals.getAddressSpace() != RQuals.getAddressSpace() ||
+ LQuals.getObjCLifetime() != RQuals.getObjCLifetime())
return QualType();
// Exactly one GC qualifier difference is allowed: __strong is
@@ -6401,4 +6499,3 @@ size_t ASTContext::getSideTableAllocatedMemory() const {
bytes += InstantiatedFromUnnamedFieldDecl.getMemorySize();
return bytes;
}
-
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 16d2f853606e..7c91b5cb7a00 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -129,7 +129,7 @@ break; \
/// \brief Convert the given type to a string suitable for printing as part of
/// a diagnostic.
///
-/// There are three main criteria when determining whether we should have an
+/// There are four main criteria when determining whether we should have an
/// a.k.a. clause when pretty-printing a type:
///
/// 1) Some types provide very minimal sugar that doesn't impede the
@@ -142,15 +142,44 @@ break; \
/// want to desugar these, even if we do produce an a.k.a. clause.
/// 3) Some types may have already been desugared previously in this diagnostic.
/// if this is the case, doing another "aka" would just be clutter.
+/// 4) Two different types within the same diagnostic have the same output
+/// string. In this case, force an a.k.a with the desugared type when
+/// doing so will provide additional information.
///
/// \param Context the context in which the type was allocated
/// \param Ty the type to print
+/// \param QualTypeVals pointer values to QualTypes which are used in the
+/// diagnostic message
static std::string
ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
const Diagnostic::ArgumentValue *PrevArgs,
- unsigned NumPrevArgs) {
+ unsigned NumPrevArgs,
+ llvm::SmallVectorImpl<intptr_t> &QualTypeVals) {
// FIXME: Playing with std::string is really slow.
+ bool ForceAKA = false;
+ QualType CanTy = Ty.getCanonicalType();
std::string S = Ty.getAsString(Context.PrintingPolicy);
+ std::string CanS = CanTy.getAsString(Context.PrintingPolicy);
+
+ for (llvm::SmallVectorImpl<intptr_t>::iterator I = QualTypeVals.begin(),
+ E = QualTypeVals.end(); I != E; ++I) {
+ QualType CompareTy =
+ QualType::getFromOpaquePtr(reinterpret_cast<void*>(*I));
+ if (CompareTy == Ty)
+ continue; // Same types
+ QualType CompareCanTy = CompareTy.getCanonicalType();
+ if (CompareCanTy == CanTy)
+ continue; // Same canonical types
+ std::string CompareS = CompareTy.getAsString(Context.PrintingPolicy);
+ if (CompareS != S)
+ continue; // Original strings are different
+ std::string CompareCanS = CompareCanTy.getAsString(Context.PrintingPolicy);
+ if (CompareCanS == CanS)
+ continue; // No new info from canonical type
+
+ ForceAKA = true;
+ break;
+ }
// Check to see if we already desugared this type in this
// diagnostic. If so, don't do it again.
@@ -172,11 +201,15 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
if (!Repeated) {
bool ShouldAKA = false;
QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA);
- if (ShouldAKA) {
- S = "'" + S + "' (aka '";
- S += DesugaredTy.getAsString(Context.PrintingPolicy);
- S += "')";
- return S;
+ if (ShouldAKA || ForceAKA) {
+ if (DesugaredTy == Ty) {
+ DesugaredTy = Ty.getCanonicalType();
+ }
+ std::string akaStr = DesugaredTy.getAsString(Context.PrintingPolicy);
+ if (akaStr != S) {
+ S = "'" + S + "' (aka '" + akaStr + "')";
+ return S;
+ }
}
}
@@ -184,16 +217,18 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
return S;
}
-void clang::FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind,
- intptr_t Val,
- const char *Modifier,
- unsigned ModLen,
- const char *Argument,
- unsigned ArgLen,
- const Diagnostic::ArgumentValue *PrevArgs,
- unsigned NumPrevArgs,
- llvm::SmallVectorImpl<char> &Output,
- void *Cookie) {
+void clang::FormatASTNodeDiagnosticArgument(
+ Diagnostic::ArgumentKind Kind,
+ intptr_t Val,
+ const char *Modifier,
+ unsigned ModLen,
+ const char *Argument,
+ unsigned ArgLen,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs,
+ llvm::SmallVectorImpl<char> &Output,
+ void *Cookie,
+ llvm::SmallVectorImpl<intptr_t> &QualTypeVals) {
ASTContext &Context = *static_cast<ASTContext*>(Cookie);
std::string S;
@@ -206,7 +241,8 @@ void clang::FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind,
"Invalid modifier for QualType argument");
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
- S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs);
+ S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs,
+ QualTypeVals);
NeedQuotes = false;
break;
}
@@ -257,7 +293,7 @@ void clang::FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind,
} else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
S = ConvertTypeToDiagnosticString(Context,
Context.getTypeDeclType(Type),
- PrevArgs, NumPrevArgs);
+ PrevArgs, NumPrevArgs, QualTypeVals);
} else {
// FIXME: Get these strings from some localized place
NamedDecl *ND = cast<NamedDecl>(DC);
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 100e604d1c46..f5e392f88d0b 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -4201,6 +4201,20 @@ TemplateName ASTImporter::Import(TemplateName From) {
return ToContext.getDependentTemplateName(Qualifier, DTN->getOperator());
}
+
+ case TemplateName::SubstTemplateTemplateParm: {
+ SubstTemplateTemplateParmStorage *subst
+ = From.getAsSubstTemplateTemplateParm();
+ TemplateTemplateParmDecl *param
+ = cast_or_null<TemplateTemplateParmDecl>(Import(subst->getParameter()));
+ if (!param)
+ return TemplateName();
+
+ TemplateName replacement = Import(subst->getReplacement());
+ if (replacement.isNull()) return TemplateName();
+
+ return ToContext.getSubstTemplateTemplateParm(param, replacement);
+ }
case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *SubstPack
@@ -4232,8 +4246,8 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
SourceManager &FromSM = FromContext.getSourceManager();
// For now, map everything down to its spelling location, so that we
- // don't have to import macro instantiations.
- // FIXME: Import macro instantiations!
+ // don't have to import macro expansions.
+ // FIXME: Import macro expansions!
FromLoc = FromSM.getSpellingLoc(FromLoc);
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
SourceManager &ToSM = ToContext.getSourceManager();
@@ -4254,7 +4268,7 @@ FileID ASTImporter::Import(FileID FromID) {
SourceManager &FromSM = FromContext.getSourceManager();
SourceManager &ToSM = ToContext.getSourceManager();
const SrcMgr::SLocEntry &FromSLoc = FromSM.getSLocEntry(FromID);
- assert(FromSLoc.isFile() && "Cannot handle macro instantiations yet");
+ assert(FromSLoc.isFile() && "Cannot handle macro expansions yet");
// Include location of this file.
SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 12357c07a794..4c323da7eee3 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -197,6 +197,16 @@ getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F);
}
+static bool shouldConsiderTemplateLV(const FunctionDecl *fn,
+ const FunctionTemplateSpecializationInfo *spec) {
+ return !(spec->isExplicitSpecialization() &&
+ fn->hasAttr<VisibilityAttr>());
+}
+
+static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) {
+ return !(d->isExplicitSpecialization() && d->hasAttr<VisibilityAttr>());
+}
+
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
@@ -231,6 +241,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (!FoundExtern)
return LinkageInfo::internal();
}
+ if (Var->getStorageClass() == SC_None) {
+ const VarDecl *PrevVar = Var->getPreviousDeclaration();
+ for (; PrevVar; PrevVar = PrevVar->getPreviousDeclaration())
+ if (PrevVar->getStorageClass() == SC_PrivateExtern)
+ break;
+ if (PrevVar)
+ return PrevVar->getLinkageAndVisibility();
+ }
} else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
// C++ [temp]p4:
// A non-member function template can have internal linkage; any
@@ -389,12 +407,16 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
Function->getType()->getLinkage() == UniqueExternalLinkage)
return LinkageInfo::uniqueExternal();
- if (FunctionTemplateSpecializationInfo *SpecInfo
+ // Consider LV from the template and the template arguments unless
+ // this is an explicit specialization with a visibility attribute.
+ if (FunctionTemplateSpecializationInfo *specInfo
= Function->getTemplateSpecializationInfo()) {
- LV.merge(getLVForDecl(SpecInfo->getTemplate(),
- F.onlyTemplateVisibility()));
- const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
- LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+ if (shouldConsiderTemplateLV(Function, specInfo)) {
+ LV.merge(getLVForDecl(specInfo->getTemplate(),
+ F.onlyTemplateVisibility()));
+ const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
+ LV.merge(getLVForTemplateArgumentList(templateArgs, F));
+ }
}
// - a named class (Clause 9), or an unnamed class defined in a
@@ -410,15 +432,17 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
// If this is a class template specialization, consider the
// linkage of the template and template arguments.
- if (const ClassTemplateSpecializationDecl *Spec
+ if (const ClassTemplateSpecializationDecl *spec
= dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
- // From the template.
- LV.merge(getLVForDecl(Spec->getSpecializedTemplate(),
- F.onlyTemplateVisibility()));
-
- // The arguments at which the template was instantiated.
- const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+ if (shouldConsiderTemplateLV(spec)) {
+ // From the template.
+ LV.merge(getLVForDecl(spec->getSpecializedTemplate(),
+ F.onlyTemplateVisibility()));
+
+ // The arguments at which the template was instantiated.
+ const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
+ LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+ }
}
// Consider -fvisibility unless the type has C linkage.
@@ -519,14 +543,16 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
// If this is a method template specialization, use the linkage for
// the template parameters and arguments.
- if (FunctionTemplateSpecializationInfo *Spec
+ if (FunctionTemplateSpecializationInfo *spec
= MD->getTemplateSpecializationInfo()) {
- LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments, F));
- if (F.ConsiderTemplateParameterTypes)
- LV.merge(getLVForTemplateParameterList(
- Spec->getTemplate()->getTemplateParameters()));
+ if (shouldConsiderTemplateLV(MD, spec)) {
+ LV.merge(getLVForTemplateArgumentList(*spec->TemplateArguments, F));
+ if (F.ConsiderTemplateParameterTypes)
+ LV.merge(getLVForTemplateParameterList(
+ spec->getTemplate()->getTemplateParameters()));
+ }
- TSK = Spec->getTemplateSpecializationKind();
+ TSK = spec->getTemplateSpecializationKind();
} else if (MemberSpecializationInfo *MSI =
MD->getMemberSpecializationInfo()) {
TSK = MSI->getTemplateSpecializationKind();
@@ -553,14 +579,16 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
// *do* apply -fvisibility to method declarations.
} else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (const ClassTemplateSpecializationDecl *Spec
+ if (const ClassTemplateSpecializationDecl *spec
= dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
- // Merge template argument/parameter information for member
- // class template specializations.
- LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F));
+ if (shouldConsiderTemplateLV(spec)) {
+ // Merge template argument/parameter information for member
+ // class template specializations.
+ LV.merge(getLVForTemplateArgumentList(spec->getTemplateArgs(), F));
if (F.ConsiderTemplateParameterTypes)
LV.merge(getLVForTemplateParameterList(
- Spec->getSpecializedTemplate()->getTemplateParameters()));
+ spec->getSpecializedTemplate()->getTemplateParameters()));
+ }
}
// Static data members.
@@ -1304,6 +1332,19 @@ void VarDecl::setInit(Expr *I) {
Init = I;
}
+bool VarDecl::extendsLifetimeOfTemporary() const {
+ assert(getType()->isReferenceType() &&"Non-references never extend lifetime");
+
+ const Expr *E = getInit();
+ if (!E)
+ return false;
+
+ if (const ExprWithCleanups *Cleanups = dyn_cast<ExprWithCleanups>(E))
+ E = Cleanups->getSubExpr();
+
+ return isa<MaterializeTemporaryExpr>(E);
+}
+
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
@@ -2320,8 +2361,15 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
ExternalASTSource::Deserializing TheFields(Source);
llvm::SmallVector<Decl*, 64> Decls;
- if (Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls))
+ LoadedFieldsFromExternalStorage = true;
+ switch (Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls)) {
+ case ELR_Success:
+ break;
+
+ case ELR_AlreadyLoaded:
+ case ELR_Failure:
return;
+ }
#ifndef NDEBUG
// Check that all decls we got were FieldDecls.
@@ -2329,8 +2377,6 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
assert(isa<FieldDecl>(Decls[i]));
#endif
- LoadedFieldsFromExternalStorage = true;
-
if (Decls.empty())
return;
@@ -2376,6 +2422,16 @@ void BlockDecl::setCaptures(ASTContext &Context,
Captures = static_cast<Capture*>(buffer);
}
+bool BlockDecl::capturesVariable(const VarDecl *variable) const {
+ for (capture_const_iterator
+ i = capture_begin(), e = capture_end(); i != e; ++i)
+ // Only auto vars can be captured, so no redeclaration worries.
+ if (i->getVariable() == variable)
+ return true;
+
+ return false;
+}
+
SourceRange BlockDecl::getSourceRange() const {
return SourceRange(getLocation(), Body? Body->getLocEnd() : getLocation());
}
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 1766d39c1405..b2806f092cbd 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -29,7 +29,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <cstdio>
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -76,26 +75,27 @@ bool Decl::CollectingStats(bool Enable) {
}
void Decl::PrintStats() {
- fprintf(stderr, "*** Decl Stats:\n");
+ llvm::errs() << "\n*** Decl Stats:\n";
int totalDecls = 0;
#define DECL(DERIVED, BASE) totalDecls += n##DERIVED##s;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
- fprintf(stderr, " %d decls total.\n", totalDecls);
+ llvm::errs() << " " << totalDecls << " decls total.\n";
int totalBytes = 0;
#define DECL(DERIVED, BASE) \
if (n##DERIVED##s > 0) { \
totalBytes += (int)(n##DERIVED##s * sizeof(DERIVED##Decl)); \
- fprintf(stderr, " %d " #DERIVED " decls, %d each (%d bytes)\n", \
- n##DERIVED##s, (int)sizeof(DERIVED##Decl), \
- (int)(n##DERIVED##s * sizeof(DERIVED##Decl))); \
+ llvm::errs() << " " << n##DERIVED##s << " " #DERIVED " decls, " \
+ << sizeof(DERIVED##Decl) << " each (" \
+ << n##DERIVED##s * sizeof(DERIVED##Decl) \
+ << " bytes)\n"; \
}
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
- fprintf(stderr, "Total bytes = %d\n", totalBytes);
+ llvm::errs() << "Total bytes = " << totalBytes << "\n";
}
void Decl::add(Kind k) {
@@ -641,12 +641,8 @@ DeclContext *Decl::getNonClosureContext() {
// This is basically "while (DC->isClosure()) DC = DC->getParent();"
// except that it's significantly more efficient to cast to a known
// decl type and call getDeclContext() than to call getParent().
- do {
- if (isa<BlockDecl>(DC)) {
- DC = cast<BlockDecl>(DC)->getDeclContext();
- continue;
- }
- } while (false);
+ while (isa<BlockDecl>(DC))
+ DC = cast<BlockDecl>(DC)->getDeclContext();
assert(!DC->isClosure());
return DC;
@@ -843,12 +839,17 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
// Notify that we have a DeclContext that is initializing.
ExternalASTSource::Deserializing ADeclContext(Source);
+ // Load the external declarations, if any.
llvm::SmallVector<Decl*, 64> Decls;
- if (Source->FindExternalLexicalDecls(this, Decls))
- return;
-
- // There is no longer any lexical storage in this context
ExternalLexicalStorage = false;
+ switch (Source->FindExternalLexicalDecls(this, Decls)) {
+ case ELR_Success:
+ break;
+
+ case ELR_Failure:
+ case ELR_AlreadyLoaded:
+ return;
+ }
if (Decls.empty())
return;
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 08ac2a5be4d9..4b59bf37d74b 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -228,6 +228,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (!BaseClassDecl->hasTrivialDestructor())
data().HasTrivialDestructor = false;
+ // A class has an Objective-C object member if... or any of its bases
+ // has an Objective-C object member.
+ if (BaseClassDecl->hasObjectMember())
+ setHasObjectMember(true);
+
// Keep track of the presence of mutable fields.
if (BaseClassDecl->hasMutableFields())
data().HasMutableFields = true;
@@ -239,22 +244,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// Create base specifier for any direct or indirect virtual bases.
data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
data().NumVBases = VBases.size();
- for (int I = 0, E = VBases.size(); I != E; ++I) {
- TypeSourceInfo *VBaseTypeInfo = VBases[I]->getTypeSourceInfo();
-
- // Skip dependent types; we can't do any checking on them now.
- if (VBaseTypeInfo->getType()->isDependentType())
- continue;
-
- CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>(
- VBaseTypeInfo->getType()->getAs<RecordType>()->getDecl());
-
- data().getVBases()[I] =
- CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
- VBaseClassDecl->getTagKind() == TTK_Class,
- VBases[I]->getAccessSpecifier(), VBaseTypeInfo,
- SourceLocation());
- }
+ for (int I = 0, E = VBases.size(); I != E; ++I)
+ data().getVBases()[I] = *VBases[I];
}
/// Callback function for CXXRecordDecl::forallBases that acknowledges
@@ -698,10 +689,23 @@ NotASpecialMember:;
// A POD struct is a class that is both a trivial class and a
// standard-layout class, and has no non-static data members of type
// non-POD struct, non-POD union (or array of such types).
+ //
+ // Automatic Reference Counting: the presence of a member of Objective-C pointer type
+ // that does not explicitly have no lifetime makes the class a non-POD.
+ // However, we delay setting PlainOldData to false in this case so that
+ // Sema has a chance to diagnostic causes where the same class will be
+ // non-POD with Automatic Reference Counting but a POD without Instant Objects.
+ // In this case, the class will become a non-POD class when we complete
+ // the definition.
ASTContext &Context = getASTContext();
QualType T = Context.getBaseElementType(Field->getType());
- if (!T->isPODType())
+ if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
+ if (!Context.getLangOptions().ObjCAutoRefCount ||
+ T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone)
+ setHasObjectMember(true);
+ } else if (!T.isPODType(Context))
data().PlainOldData = false;
+
if (T->isReferenceType()) {
data().HasTrivialDefaultConstructor = false;
@@ -768,6 +772,8 @@ NotASpecialMember:;
if (!FieldRec->hasTrivialDestructor())
data().HasTrivialDestructor = false;
+ if (FieldRec->hasObjectMember())
+ setHasObjectMember(true);
// C++0x [class]p7:
// A standard-layout class is a class that:
@@ -1078,6 +1084,20 @@ void CXXRecordDecl::completeDefinition() {
void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
RecordDecl::completeDefinition();
+ if (hasObjectMember() && getASTContext().getLangOptions().ObjCAutoRefCount) {
+ // Objective-C Automatic Reference Counting:
+ // If a class has a non-static data member of Objective-C pointer
+ // type (or array thereof), it is a non-POD type and its
+ // default constructor (if any), copy constructor, copy assignment
+ // operator, and destructor are non-trivial.
+ struct DefinitionData &Data = data();
+ Data.PlainOldData = false;
+ Data.HasTrivialDefaultConstructor = false;
+ Data.HasTrivialCopyConstructor = false;
+ Data.HasTrivialCopyAssignment = false;
+ Data.HasTrivialDestructor = false;
+ }
+
// If the class may be abstract (but hasn't been marked as such), check for
// any pure final overriders.
if (mayBeAbstract()) {
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index e2c4f38ff9be..557b681d2fa6 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -452,6 +452,34 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
if (!isInstanceMethod())
family = OMF_None;
break;
+
+ case OMF_performSelector:
+ if (!isInstanceMethod() ||
+ !getResultType()->isObjCIdType())
+ family = OMF_None;
+ else {
+ unsigned noParams = param_size();
+ if (noParams < 1 || noParams > 3)
+ family = OMF_None;
+ else {
+ ObjCMethodDecl::arg_type_iterator it = arg_type_begin();
+ QualType ArgT = (*it);
+ if (!ArgT->isObjCSelType()) {
+ family = OMF_None;
+ break;
+ }
+ while (--noParams) {
+ it++;
+ ArgT = (*it);
+ if (!ArgT->isObjCIdType()) {
+ family = OMF_None;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
}
// Cache the result.
@@ -474,8 +502,34 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
} else // we have a factory method.
selfTy = Context.getObjCClassType();
- setSelfDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
- &Context.Idents.get("self"), selfTy));
+ bool selfIsPseudoStrong = false;
+ bool selfIsConsumed = false;
+ if (isInstanceMethod() && Context.getLangOptions().ObjCAutoRefCount) {
+ selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
+
+ // 'self' is always __strong. It's actually pseudo-strong except
+ // in init methods, though.
+ Qualifiers qs;
+ qs.setObjCLifetime(Qualifiers::OCL_Strong);
+ selfTy = Context.getQualifiedType(selfTy, qs);
+
+ // In addition, 'self' is const unless this is an init method.
+ if (getMethodFamily() != OMF_init) {
+ selfTy = selfTy.withConst();
+ selfIsPseudoStrong = true;
+ }
+ }
+
+ ImplicitParamDecl *self
+ = ImplicitParamDecl::Create(Context, this, SourceLocation(),
+ &Context.Idents.get("self"), selfTy);
+ setSelfDecl(self);
+
+ if (selfIsConsumed)
+ self->addAttr(new (Context) NSConsumedAttr(SourceLocation(), Context));
+
+ if (selfIsPseudoStrong)
+ self->setARCPseudoStrong(true);
setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
&Context.Idents.get("_cmd"),
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 421770ea70fb..19554a3baaea 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -933,6 +933,11 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
first = false;
}
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
+ Out << (first ? ' ' : ',') << "strong";
+ first = false;
+ }
+
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
Out << (first ? ' ' : ',') << "copy";
first = false;
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index cef54e97c93a..72c0e9da7f1d 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -533,6 +533,28 @@ bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
llvm_unreachable("All name kinds handled.");
}
+bool DeclarationNameInfo::isInstantiationDependent() const {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXUsingDirective:
+ return false;
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
+ return TInfo->getType()->isInstantiationDependentType();
+
+ return Name.getCXXNameType()->isInstantiationDependentType();
+ }
+ llvm_unreachable("All name kinds handled.");
+}
+
std::string DeclarationNameInfo::getAsString() const {
std::string Result;
llvm::raw_string_ostream OS(Result);
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 987213907e45..4611ae369969 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -142,9 +142,10 @@ void ExplicitTemplateArgumentList::initializeFrom(
}
void ExplicitTemplateArgumentList::initializeFrom(
- const TemplateArgumentListInfo &Info,
- bool &Dependent,
- bool &ContainsUnexpandedParameterPack) {
+ const TemplateArgumentListInfo &Info,
+ bool &Dependent,
+ bool &InstantiationDependent,
+ bool &ContainsUnexpandedParameterPack) {
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
@@ -152,6 +153,8 @@ void ExplicitTemplateArgumentList::initializeFrom(
TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
for (unsigned i = 0; i != NumTemplateArgs; ++i) {
Dependent = Dependent || Info[i].getArgument().isDependent();
+ InstantiationDependent = InstantiationDependent ||
+ Info[i].getArgument().isInstantiationDependent();
ContainsUnexpandedParameterPack
= ContainsUnexpandedParameterPack ||
Info[i].getArgument().containsUnexpandedParameterPack();
@@ -178,14 +181,16 @@ std::size_t ExplicitTemplateArgumentList::sizeFor(
return sizeFor(Info.size());
}
-/// \brief Compute the type- and value-dependence of a declaration reference
+/// \brief Compute the type-, value-, and instantiation-dependence of a
+/// declaration reference
/// based on the declaration being referenced.
static void computeDeclRefDependence(NamedDecl *D, QualType T,
bool &TypeDependent,
- bool &ValueDependent) {
+ bool &ValueDependent,
+ bool &InstantiationDependent) {
TypeDependent = false;
ValueDependent = false;
-
+ InstantiationDependent = false;
// (TD) C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
@@ -200,20 +205,31 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T,
if (T->isDependentType()) {
TypeDependent = true;
ValueDependent = true;
+ InstantiationDependent = true;
return;
+ } else if (T->isInstantiationDependentType()) {
+ InstantiationDependent = true;
}
// (TD) - a conversion-function-id that specifies a dependent type
if (D->getDeclName().getNameKind()
- == DeclarationName::CXXConversionFunctionName &&
- D->getDeclName().getCXXNameType()->isDependentType()) {
- TypeDependent = true;
- ValueDependent = true;
- return;
+ == DeclarationName::CXXConversionFunctionName) {
+ QualType T = D->getDeclName().getCXXNameType();
+ if (T->isDependentType()) {
+ TypeDependent = true;
+ ValueDependent = true;
+ InstantiationDependent = true;
+ return;
+ }
+
+ if (T->isInstantiationDependentType())
+ InstantiationDependent = true;
}
+
// (VD) - the name of a non-type template parameter,
if (isa<NonTypeTemplateParmDecl>(D)) {
ValueDependent = true;
+ InstantiationDependent = true;
return;
}
@@ -223,16 +239,20 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T,
if (Var->getType()->isIntegralOrEnumerationType() &&
Var->getType().getCVRQualifiers() == Qualifiers::Const) {
if (const Expr *Init = Var->getAnyInitializer())
- if (Init->isValueDependent())
+ if (Init->isValueDependent()) {
ValueDependent = true;
+ InstantiationDependent = true;
+ }
}
// (VD) - FIXME: Missing from the standard:
// - a member function or a static data member of the current
// instantiation
else if (Var->isStaticDataMember() &&
- Var->getDeclContext()->isDependentContext())
+ Var->getDeclContext()->isDependentContext()) {
ValueDependent = true;
+ InstantiationDependent = true;
+ }
return;
}
@@ -242,6 +262,7 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T,
// instantiation
if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) {
ValueDependent = true;
+ InstantiationDependent = true;
return;
}
}
@@ -249,7 +270,9 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T,
void DeclRefExpr::computeDependence() {
bool TypeDependent = false;
bool ValueDependent = false;
- computeDeclRefDependence(getDecl(), getType(), TypeDependent, ValueDependent);
+ bool InstantiationDependent = false;
+ computeDeclRefDependence(getDecl(), getType(), TypeDependent, ValueDependent,
+ InstantiationDependent);
// (TD) C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
@@ -262,13 +285,16 @@ void DeclRefExpr::computeDependence() {
hasExplicitTemplateArgs() &&
TemplateSpecializationType::anyDependentTemplateArguments(
getTemplateArgs(),
- getNumTemplateArgs())) {
+ getNumTemplateArgs(),
+ InstantiationDependent)) {
TypeDependent = true;
ValueDependent = true;
+ InstantiationDependent = true;
}
ExprBits.TypeDependent = TypeDependent;
ExprBits.ValueDependent = ValueDependent;
+ ExprBits.InstantiationDependent = InstantiationDependent;
// Is the declaration a parameter pack?
if (getDecl()->isParameterPack())
@@ -280,7 +306,7 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
QualType T, ExprValueKind VK)
- : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false),
+ : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) {
DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0;
if (QualifierLoc)
@@ -289,9 +315,17 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc,
if (FoundD)
getInternalFoundDecl() = FoundD;
DeclRefExprBits.HasExplicitTemplateArgs = TemplateArgs ? 1 : 0;
- if (TemplateArgs)
- getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
-
+ if (TemplateArgs) {
+ bool Dependent = false;
+ bool InstantiationDependent = false;
+ bool ContainsUnexpandedParameterPack = false;
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent,
+ InstantiationDependent,
+ ContainsUnexpandedParameterPack);
+ if (InstantiationDependent)
+ setInstantiationDependent(true);
+ }
+
computeDependence();
}
@@ -498,8 +532,8 @@ double FloatingLiteral::getValueAsApproximateDouble() const {
return V.convertToDouble();
}
-StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData,
- unsigned ByteLength, bool Wide,
+StringLiteral *StringLiteral::Create(ASTContext &C, llvm::StringRef Str,
+ bool Wide,
bool Pascal, QualType Ty,
const SourceLocation *Loc,
unsigned NumStrs) {
@@ -511,10 +545,10 @@ StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData,
StringLiteral *SL = new (Mem) StringLiteral(Ty);
// OPTIMIZE: could allocate this appended to the StringLiteral.
- char *AStrData = new (C, 1) char[ByteLength];
- memcpy(AStrData, StrData, ByteLength);
+ char *AStrData = new (C, 1) char[Str.size()];
+ memcpy(AStrData, Str.data(), Str.size());
SL->StrData = AStrData;
- SL->ByteLength = ByteLength;
+ SL->ByteLength = Str.size();
SL->IsWide = Wide;
SL->IsPascal = Pascal;
SL->TokLocs[0] = Loc[0];
@@ -593,7 +627,7 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
// If the byte is in this token, return the location of the byte.
if (ByteNo < TokNumBytes ||
- (ByteNo == TokNumBytes && TokNo == getNumConcatenated())) {
+ (ByteNo == TokNumBytes && TokNo == getNumConcatenated() - 1)) {
unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo);
// Now that we know the offset of the token in the spelling, use the
@@ -670,6 +704,7 @@ CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
: Expr(SC, t, VK, OK_Ordinary,
fn->isTypeDependent(),
fn->isValueDependent(),
+ fn->isInstantiationDependent(),
fn->containsUnexpandedParameterPack()),
NumArgs(numargs) {
@@ -680,6 +715,8 @@ CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
ExprBits.ValueDependent = true;
+ if (args[i]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -695,6 +732,7 @@ CallExpr::CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs,
: Expr(CallExprClass, t, VK, OK_Ordinary,
fn->isTypeDependent(),
fn->isValueDependent(),
+ fn->isInstantiationDependent(),
fn->containsUnexpandedParameterPack()),
NumArgs(numargs) {
@@ -705,6 +743,8 @@ CallExpr::CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs,
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
ExprBits.ValueDependent = true;
+ if (args[i]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -862,6 +902,7 @@ OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type,
: Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary,
/*TypeDependent=*/false,
/*ValueDependent=*/tsi->getType()->isDependentType(),
+ tsi->getType()->isInstantiationDependentType(),
tsi->getType()->containsUnexpandedParameterPack()),
OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi),
NumComps(numComps), NumExprs(numExprs)
@@ -917,7 +958,12 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) {
E->setValueDependent(true);
E->setTypeDependent(true);
- }
+ E->setInstantiationDependent(true);
+ }
+ else if (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
+ E->setInstantiationDependent(true);
+
E->HasQualifierOrFoundDecl = true;
MemberNameQualifier *NQ = E->getMemberQualifier();
@@ -926,8 +972,15 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
}
if (targs) {
+ bool Dependent = false;
+ bool InstantiationDependent = false;
+ bool ContainsUnexpandedParameterPack = false;
E->HasExplicitTemplateArgumentList = true;
- E->getExplicitTemplateArgs().initializeFrom(*targs);
+ E->getExplicitTemplateArgs().initializeFrom(*targs, Dependent,
+ InstantiationDependent,
+ ContainsUnexpandedParameterPack);
+ if (InstantiationDependent)
+ E->setInstantiationDependent(true);
}
return E;
@@ -1045,6 +1098,12 @@ const char *CastExpr::getCastKindName() const {
return "IntegralComplexCast";
case CK_IntegralComplexToFloatingComplex:
return "IntegralComplexToFloatingComplex";
+ case CK_ObjCConsumeObject:
+ return "ObjCConsumeObject";
+ case CK_ObjCProduceObject:
+ return "ObjCProduceObject";
+ case CK_ObjCReclaimReturnedObject:
+ return "ObjCReclaimReturnedObject";
}
llvm_unreachable("Unhandled cast kind!");
@@ -1056,7 +1115,12 @@ Expr *CastExpr::getSubExprAsWritten() {
CastExpr *E = this;
do {
SubExpr = E->getSubExpr();
-
+
+ // Skip through reference binding to temporary.
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(SubExpr))
+ SubExpr = Materialize->GetTemporaryExpr();
+
// Skip any temporary bindings; they're implicit.
if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
SubExpr = Binder->getSubExpr();
@@ -1242,7 +1306,7 @@ InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc,
Expr **initExprs, unsigned numInits,
SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
- false),
+ false, false),
InitExprs(C, numInits),
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
HadArrayRangeDesignator(false)
@@ -1252,6 +1316,8 @@ InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc,
ExprBits.TypeDependent = true;
if (initExprs[I]->isValueDependent())
ExprBits.ValueDependent = true;
+ if (initExprs[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (initExprs[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
}
@@ -1490,6 +1556,17 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case ObjCMessageExprClass: {
const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this);
+ if (Ctx.getLangOptions().ObjCAutoRefCount &&
+ ME->isInstanceMessage() &&
+ !ME->getType()->isVoidType() &&
+ ME->getSelector().getIdentifierInfoForSlot(0) &&
+ ME->getSelector().getIdentifierInfoForSlot(0)
+ ->getName().startswith("init")) {
+ Loc = getExprLoc();
+ R1 = ME->getSourceRange();
+ return true;
+ }
+
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
Loc = getExprLoc();
@@ -1584,6 +1661,9 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
return cast<UnaryOperator>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case ImplicitCastExprClass:
return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
+ case MaterializeTemporaryExprClass:
+ return cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr()
+ ->isOBJCGCCandidate(Ctx);
case CStyleCastExprClass:
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case DeclRefExprClass: {
@@ -1858,7 +1938,8 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
case CXXStaticCastExprClass:
case CXXFunctionalCastExprClass:
case BinaryOperatorClass:
- case CompoundAssignOperatorClass: {
+ case CompoundAssignOperatorClass:
+ case MaterializeTemporaryExprClass: {
CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
@@ -1938,6 +2019,12 @@ Expr *Expr::IgnoreParenCasts() {
continue;
}
}
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = Materialize->GetTemporaryExpr();
+ continue;
+ }
+
return E;
}
}
@@ -1967,6 +2054,10 @@ Expr *Expr::IgnoreParenLValueCasts() {
E = P->getResultExpr();
continue;
}
+ } else if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = Materialize->GetTemporaryExpr();
+ continue;
}
break;
}
@@ -1996,13 +2087,18 @@ Expr *Expr::IgnoreParenImpCasts() {
continue;
}
}
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = Materialize->GetTemporaryExpr();
+ continue;
+ }
return E;
}
}
Expr *Expr::IgnoreConversionOperator() {
if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(this)) {
- if (isa<CXXConversionDecl>(MCE->getMethodDecl()))
+ if (MCE->getMethodDecl() && isa<CXXConversionDecl>(MCE->getMethodDecl()))
return MCE->getImplicitObjectArgument();
}
return this;
@@ -2059,6 +2155,9 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
bool Expr::isDefaultArgument() const {
const Expr *E = this;
+ if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = M->GetTemporaryExpr();
+
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExprAsWritten();
@@ -2068,6 +2167,9 @@ bool Expr::isDefaultArgument() const {
/// \brief Skip over any no-op casts and any temporary-binding
/// expressions.
static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
+ if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = M->GetTemporaryExpr();
+
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr();
@@ -2155,6 +2257,12 @@ bool Expr::isImplicitCXXThis() const {
}
}
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = M->GetTemporaryExpr();
+ continue;
+ }
+
break;
}
@@ -2287,6 +2395,10 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
->isConstantInitializer(Ctx, false);
break;
+
+ case MaterializeTemporaryExprClass:
+ return llvm::cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
+ ->isConstantInitializer(Ctx, false);
}
return isEvaluatable(Ctx);
}
@@ -2345,6 +2457,9 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
} else if (isa<GNUNullExpr>(this)) {
// The GNU __null extension is always a null pointer constant.
return NPCK_GNUNull;
+ } else if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(this)) {
+ return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC);
}
// C++0x nullptr_t is always a null pointer constant.
@@ -2414,10 +2529,14 @@ FieldDecl *Expr::getBitField() {
if (Field->isBitField())
return Field;
- if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E))
+ if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) {
if (BinOp->isAssignmentOp() && BinOp->getLHS())
return BinOp->getLHS()->getBitField();
+ if (BinOp->getOpcode() == BO_Comma && BinOp->getRHS())
+ return BinOp->getRHS()->getBitField();
+ }
+
return 0;
}
@@ -2517,9 +2636,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SourceLocation RBracLoc)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
/*TypeDependent=*/false, /*ValueDependent=*/false,
+ /*InstantiationDependent=*/false,
/*ContainsUnexpandedParameterPack=*/false),
NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass),
- HasMethod(Method != 0), SuperLoc(SuperLoc),
+ HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
@@ -2539,8 +2659,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
- T->isDependentType(), T->containsUnexpandedParameterPack()),
- NumArgs(NumArgs), Kind(Class), HasMethod(Method != 0),
+ T->isDependentType(), T->isInstantiationDependentType(),
+ T->containsUnexpandedParameterPack()),
+ NumArgs(NumArgs), Kind(Class),
+ HasMethod(Method != 0), IsDelegateInitCall(false),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
@@ -2552,6 +2674,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
ExprBits.TypeDependent = true;
if (Args[I]->isValueDependent())
ExprBits.ValueDependent = true;
+ if (Args[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (Args[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -2570,8 +2694,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SourceLocation RBracLoc)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(),
Receiver->isTypeDependent(),
+ Receiver->isInstantiationDependent(),
Receiver->containsUnexpandedParameterPack()),
- NumArgs(NumArgs), Kind(Instance), HasMethod(Method != 0),
+ NumArgs(NumArgs), Kind(Instance),
+ HasMethod(Method != 0), IsDelegateInitCall(false),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
@@ -2583,6 +2709,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
ExprBits.TypeDependent = true;
if (Args[I]->isValueDependent())
ExprBits.ValueDependent = true;
+ if (Args[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (Args[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -2702,6 +2830,19 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
return 0;
}
+llvm::StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
+ switch (getBridgeKind()) {
+ case OBC_Bridge:
+ return "__bridge";
+ case OBC_BridgeTransfer:
+ return "__bridge_transfer";
+ case OBC_BridgeRetained:
+ return "__bridge_retained";
+ }
+
+ return "__bridge";
+}
+
bool ChooseExpr::isConditionTrue(const ASTContext &C) const {
return getCond()->EvaluateAsInt(C) != 0;
}
@@ -2711,6 +2852,7 @@ ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
SourceLocation RP)
: Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary,
Type->isDependentType(), Type->isDependentType(),
+ Type->isInstantiationDependentType(),
Type->containsUnexpandedParameterPack()),
BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr)
{
@@ -2720,6 +2862,8 @@ ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
ExprBits.ValueDependent = true;
+ if (args[i]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -2749,6 +2893,7 @@ GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
AssocExprs[ResultIndex]->getObjectKind(),
AssocExprs[ResultIndex]->isTypeDependent(),
AssocExprs[ResultIndex]->isValueDependent(),
+ AssocExprs[ResultIndex]->isInstantiationDependent(),
ContainsUnexpandedParameterPack),
AssocTypes(new (Context) TypeSourceInfo*[NumAssocs]),
SubExprs(new (Context) Stmt*[END_EXPR+NumAssocs]), NumAssocs(NumAssocs),
@@ -2769,8 +2914,9 @@ GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
Context.DependentTy,
VK_RValue,
OK_Ordinary,
- /*isTypeDependent=*/ true,
- /*isValueDependent=*/ true,
+ /*isTypeDependent=*/true,
+ /*isValueDependent=*/true,
+ /*isInstantiationDependent=*/true,
ContainsUnexpandedParameterPack),
AssocTypes(new (Context) TypeSourceInfo*[NumAssocs]),
SubExprs(new (Context) Stmt*[END_EXPR+NumAssocs]), NumAssocs(NumAssocs),
@@ -2785,7 +2931,7 @@ GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
// DesignatedInitExpr
//===----------------------------------------------------------------------===//
-IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() {
+IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() const {
assert(Kind == FieldDesignator && "Only valid on a field designator");
if (Field.NameOrField & 0x01)
return reinterpret_cast<IdentifierInfo *>(Field.NameOrField&~0x01);
@@ -2804,6 +2950,7 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
: Expr(DesignatedInitExprClass, Ty,
Init->getValueKind(), Init->getObjectKind(),
Init->isTypeDependent(), Init->isValueDependent(),
+ Init->isInstantiationDependent(),
Init->containsUnexpandedParameterPack()),
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) {
@@ -2824,7 +2971,8 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
Expr *Index = IndexExprs[IndexIdx];
if (Index->isTypeDependent() || Index->isValueDependent())
ExprBits.ValueDependent = true;
-
+ if (Index->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
// Propagate unexpanded parameter packs.
if (Index->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -2836,9 +2984,14 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
Expr *Start = IndexExprs[IndexIdx];
Expr *End = IndexExprs[IndexIdx + 1];
if (Start->isTypeDependent() || Start->isValueDependent() ||
- End->isTypeDependent() || End->isValueDependent())
+ End->isTypeDependent() || End->isValueDependent()) {
ExprBits.ValueDependent = true;
-
+ ExprBits.InstantiationDependent = true;
+ } else if (Start->isInstantiationDependent() ||
+ End->isInstantiationDependent()) {
+ ExprBits.InstantiationDependent = true;
+ }
+
// Propagate unexpanded parameter packs.
if (Start->containsUnexpandedParameterPack() ||
End->containsUnexpandedParameterPack())
@@ -2960,17 +3113,19 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Expr **exprs, unsigned nexprs,
- SourceLocation rparenloc)
- : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary,
- false, false, false),
+ SourceLocation rparenloc, QualType T)
+ : Expr(ParenListExprClass, T, VK_RValue, OK_Ordinary,
+ false, false, false, false),
NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) {
-
+ assert(!T.isNull() && "ParenListExpr must have a valid type");
Exprs = new (C) Stmt*[nexprs];
for (unsigned i = 0; i != nexprs; ++i) {
if (exprs[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (exprs[i]->isValueDependent())
ExprBits.ValueDependent = true;
+ if (exprs[i]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (exprs[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -2981,6 +3136,8 @@ ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
e = ewc->getSubExpr();
+ if (const MaterializeTemporaryExpr *m = dyn_cast<MaterializeTemporaryExpr>(e))
+ e = m->GetTemporaryExpr();
e = cast<CXXConstructExpr>(e)->getArg(0);
while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
e = ice->getSubExpr();
@@ -3033,13 +3190,16 @@ Stmt::child_range ObjCMessageExpr::children() {
BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
SourceLocation l, bool ByRef,
bool constAdded)
- : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, false, false,
+ : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, false, false, false,
d->isParameterPack()),
D(d), Loc(l), IsByRef(ByRef), ConstQualAdded(constAdded)
{
bool TypeDependent = false;
bool ValueDependent = false;
- computeDeclRefDependence(D, getType(), TypeDependent, ValueDependent);
+ bool InstantiationDependent = false;
+ computeDeclRefDependence(D, getType(), TypeDependent, ValueDependent,
+ InstantiationDependent);
ExprBits.TypeDependent = TypeDependent;
ExprBits.ValueDependent = ValueDependent;
+ ExprBits.InstantiationDependent = InstantiationDependent;
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 1a1a0a36a65b..f92afffb5851 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -57,6 +57,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
SourceLocation constructorRParen)
: Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary,
ty->isDependentType(), ty->isDependentType(),
+ ty->isInstantiationDependentType(),
ty->containsUnexpandedParameterPack()),
GlobalNew(globalNew), Initializer(initializer),
UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize),
@@ -68,6 +69,9 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs);
unsigned i = 0;
if (Array) {
+ if (arraySize->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+
if (arraySize->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -75,6 +79,8 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
}
for (unsigned j = 0; j < NumPlacementArgs; ++j) {
+ if (placementArgs[j]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (placementArgs[j]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -82,6 +88,8 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
}
for (unsigned j = 0; j < NumConstructorArgs; ++j) {
+ if (constructorArgs[j]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (constructorArgs[j]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -144,6 +152,14 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context,
(DestroyedType.getTypeSourceInfo() &&
DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),
/*isValueDependent=*/Base->isValueDependent(),
+ (Base->isInstantiationDependent() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) ||
+ (ScopeType &&
+ ScopeType->getType()->isInstantiationDependentType()) ||
+ (DestroyedType.getTypeSourceInfo() &&
+ DestroyedType.getTypeSourceInfo()->getType()
+ ->isInstantiationDependentType())),
// ContainsUnexpandedParameterPack
(Base->containsUnexpandedParameterPack() ||
(QualifierLoc &&
@@ -212,9 +228,14 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End,
bool KnownDependent,
+ bool KnownInstantiationDependent,
bool KnownContainsUnexpandedParameterPack)
: Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
KnownDependent,
+ (KnownInstantiationDependent ||
+ NameInfo.isInstantiationDependent() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
(KnownContainsUnexpandedParameterPack ||
NameInfo.containsUnexpandedParameterPack() ||
(QualifierLoc &&
@@ -246,14 +267,18 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C,
// expansions.
if (TemplateArgs) {
bool Dependent = false;
+ bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent,
+ InstantiationDependent,
ContainsUnexpandedParameterPack);
if (Dependent) {
- ExprBits.TypeDependent = true;
- ExprBits.ValueDependent = true;
- }
+ ExprBits.TypeDependent = true;
+ ExprBits.ValueDependent = true;
+ }
+ if (InstantiationDependent)
+ ExprBits.InstantiationDependent = true;
if (ContainsUnexpandedParameterPack)
ExprBits.ContainsUnexpandedParameterPack = true;
}
@@ -291,6 +316,9 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
const TemplateArgumentListInfo *Args)
: Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary,
true, true,
+ (NameInfo.isInstantiationDependent() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
(NameInfo.containsUnexpandedParameterPack() ||
(QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()
@@ -300,11 +328,14 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
{
if (Args) {
bool Dependent = true;
+ bool InstantiationDependent = true;
bool ContainsUnexpandedParameterPack
= ExprBits.ContainsUnexpandedParameterPack;
reinterpret_cast<ExplicitTemplateArgumentList*>(this+1)
- ->initializeFrom(*Args, Dependent, ContainsUnexpandedParameterPack);
+ ->initializeFrom(*Args, Dependent, InstantiationDependent,
+ ContainsUnexpandedParameterPack);
+
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
}
}
@@ -632,6 +663,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
SourceRange ParenRange)
: Expr(SC, T, VK_RValue, OK_Ordinary,
T->isDependentType(), T->isDependentType(),
+ T->isInstantiationDependentType(),
T->containsUnexpandedParameterPack()),
Constructor(D), Loc(Loc), ParenRange(ParenRange), Elidable(elidable),
ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind),
@@ -645,6 +677,8 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
if (args[i]->isValueDependent())
ExprBits.ValueDependent = true;
+ if (args[i]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
if (args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -660,6 +694,7 @@ ExprWithCleanups::ExprWithCleanups(ASTContext &C,
: Expr(ExprWithCleanupsClass, subexpr->getType(),
subexpr->getValueKind(), subexpr->getObjectKind(),
subexpr->isTypeDependent(), subexpr->isValueDependent(),
+ subexpr->isInstantiationDependent(),
subexpr->containsUnexpandedParameterPack()),
SubExpr(subexpr), Temps(0), NumTemps(0) {
if (numtemps) {
@@ -690,8 +725,11 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
SourceLocation RParenLoc)
: Expr(CXXUnresolvedConstructExprClass,
Type->getType().getNonReferenceType(),
- VK_LValue, OK_Ordinary,
- Type->getType()->isDependentType(), true,
+ (Type->getType()->isLValueReferenceType() ? VK_LValue
+ :Type->getType()->isRValueReferenceType()? VK_XValue
+ :VK_RValue),
+ OK_Ordinary,
+ Type->getType()->isDependentType(), true, true,
Type->getType()->containsUnexpandedParameterPack()),
Type(Type),
LParenLoc(LParenLoc),
@@ -740,7 +778,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy,
- VK_LValue, OK_Ordinary, true, true,
+ VK_LValue, OK_Ordinary, true, true, true,
((Base && Base->containsUnexpandedParameterPack()) ||
(QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()
@@ -753,8 +791,10 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
MemberNameInfo(MemberNameInfo) {
if (TemplateArgs) {
bool Dependent = true;
+ bool InstantiationDependent = true;
bool ContainsUnexpandedParameterPack = false;
getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent,
+ InstantiationDependent,
ContainsUnexpandedParameterPack);
if (ContainsUnexpandedParameterPack)
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -769,7 +809,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy,
- VK_LValue, OK_Ordinary, true, true,
+ VK_LValue, OK_Ordinary, true, true, true,
((Base && Base->containsUnexpandedParameterPack()) ||
(QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()->
@@ -874,6 +914,8 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C,
// Dependent
((Base && Base->isTypeDependent()) ||
BaseType->isDependentType()),
+ ((Base && Base->isInstantiationDependent()) ||
+ BaseType->isInstantiationDependentType()),
// Contains unexpanded parameter pack
((Base && Base->containsUnexpandedParameterPack()) ||
BaseType->containsUnexpandedParameterPack())),
@@ -962,7 +1004,7 @@ SubstNonTypeTemplateParmPackExpr(QualType T,
SourceLocation NameLoc,
const TemplateArgument &ArgPack)
: Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary,
- true, false, true),
+ true, true, true, true),
Param(Param), Arguments(ArgPack.pack_begin()),
NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { }
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index d177cb5cbc97..e7888a6aa7b3 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -117,7 +117,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::UnresolvedLookupExprClass:
case Expr::UnresolvedMemberExprClass:
case Expr::CXXDependentScopeMemberExprClass:
- case Expr::CXXUnresolvedConstructExprClass:
case Expr::DependentScopeDeclRefExprClass:
// ObjC instance variables are lvalues
// FIXME: ObjC++0x might have different rules
@@ -162,9 +161,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::SizeOfPackExprClass:
case Expr::SubstNonTypeTemplateParmPackExprClass:
case Expr::AsTypeExprClass:
+ case Expr::ObjCIndirectCopyRestoreExprClass:
return Cl::CL_PRValue;
// Next come the complicated cases.
+ case Expr::SubstNonTypeTemplateParmExprClass:
+ return ClassifyInternal(Ctx,
+ cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
// C++ [expr.sub]p1: The result is an lvalue of type "T".
// However, subscripting vector types is more like member access.
@@ -289,10 +292,15 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CXXDynamicCastExprClass:
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXConstCastExprClass:
+ case Expr::ObjCBridgedCastExprClass:
// Only in C++ can casts be interesting at all.
if (!Lang.CPlusPlus) return Cl::CL_PRValue;
return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten());
+ case Expr::CXXUnresolvedConstructExprClass:
+ return ClassifyUnnamed(Ctx,
+ cast<CXXUnresolvedConstructExpr>(E)->getTypeAsWritten());
+
case Expr::BinaryConditionalOperatorClass: {
if (!Lang.CPlusPlus) return Cl::CL_PRValue;
const BinaryConditionalOperator *co = cast<BinaryConditionalOperator>(E);
@@ -339,6 +347,11 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::PackExpansionExprClass:
return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern());
+
+ case Expr::MaterializeTemporaryExprClass:
+ return cast<MaterializeTemporaryExpr>(E)->isBoundToLvalueReference()
+ ? Cl::CL_LValue
+ : Cl::CL_XValue;
}
llvm_unreachable("unhandled expression kind in classification");
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 06c5645afb3f..786155af281d 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -224,11 +224,10 @@ static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType,
bool DestSigned = DestType->isSignedIntegerOrEnumerationType();
// FIXME: Warning for overflow.
- uint64_t Space[4];
+ APSInt Result(DestWidth, !DestSigned);
bool ignored;
- (void)Value.convertToInteger(Space, DestWidth, DestSigned,
- llvm::APFloat::rmTowardZero, &ignored);
- return APSInt(llvm::APInt(DestWidth, 4, Space), !DestSigned);
+ (void)Value.convertToInteger(Result, llvm::APFloat::rmTowardZero, &ignored);
+ return Result;
}
static APFloat HandleFloatToFloatCast(QualType DestType, QualType SrcType,
@@ -282,6 +281,17 @@ public:
return true;
return false;
}
+ bool VisitObjCIvarRefExpr(const ObjCIvarRefExpr *E) {
+ if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ return true;
+ return false;
+ }
+ bool VisitBlockDeclRefExpr (const BlockDeclRefExpr *E) {
+ if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ return true;
+ return false;
+ }
+
// We don't want to evaluate BlockExprs multiple times, as they generate
// a ton of code.
bool VisitBlockExpr(const BlockExpr *E) { return true; }
@@ -395,6 +405,8 @@ public:
{ return StmtVisitorTy::Visit(E->getChosenSubExpr(Info.Ctx)); }
RetTy VisitGenericSelectionExpr(const GenericSelectionExpr *E)
{ return StmtVisitorTy::Visit(E->getResultExpr()); }
+ RetTy VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
+ { return StmtVisitorTy::Visit(E->getReplacement()); }
RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) {
OpaqueValueEvaluation opaque(Info, E->getOpaqueValue(), E->getCommon());
@@ -525,15 +537,7 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
if (FD->getType()->isReferenceType())
return false;
- // FIXME: This is linear time.
- unsigned i = 0;
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end();
- Field != FieldEnd; (void)++Field, ++i) {
- if (*Field == FD)
- break;
- }
-
+ unsigned i = FD->getFieldIndex();
Result.Offset += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i));
return true;
}
@@ -945,7 +949,7 @@ public:
: ExprEvaluatorBaseTy(info), Result(result) {}
bool Success(const llvm::APSInt &SI, const Expr *E) {
- assert(E->getType()->isIntegralOrEnumerationType() &&
+ assert(E->getType()->isIntegralOrEnumerationType() &&
"Invalid evaluation result.");
assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() &&
"Invalid evaluation result.");
@@ -1095,8 +1099,25 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
// Enums are integer constant exprs.
- if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
- return Success(ECD->getInitVal(), E);
+ if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
+ // Check for signedness/width mismatches between E type and ECD value.
+ bool SameSign = (ECD->getInitVal().isSigned()
+ == E->getType()->isSignedIntegerOrEnumerationType());
+ bool SameWidth = (ECD->getInitVal().getBitWidth()
+ == Info.Ctx.getIntWidth(E->getType()));
+ if (SameSign && SameWidth)
+ return Success(ECD->getInitVal(), E);
+ else {
+ // Get rid of mismatch (otherwise Success assertions will fail)
+ // by computing a new value matching the type of E.
+ llvm::APSInt Val = ECD->getInitVal();
+ if (!SameSign)
+ Val.setIsSigned(!ECD->getInitVal().isSigned());
+ if (!SameWidth)
+ Val = Val.extOrTrunc(Info.Ctx.getIntWidth(E->getType()));
+ return Success(Val, E);
+ }
+ }
// In C++, const, non-volatile integers initialized with ICEs are ICEs.
// In C, they can also be folded, although they are not ICEs.
@@ -1797,6 +1818,9 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_GetObjCProperty:
case CK_LValueBitCast:
case CK_UserDefinedConversion:
+ case CK_ObjCProduceObject:
+ case CK_ObjCConsumeObject:
+ case CK_ObjCReclaimReturnedObject:
return false;
case CK_LValueToRValue:
@@ -2301,6 +2325,9 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_FloatingComplexToBoolean:
case CK_IntegralComplexToReal:
case CK_IntegralComplexToBoolean:
+ case CK_ObjCProduceObject:
+ case CK_ObjCConsumeObject:
+ case CK_ObjCReclaimReturnedObject:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
@@ -2771,6 +2798,8 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::PackExpansionExprClass:
case Expr::SubstNonTypeTemplateParmPackExprClass:
case Expr::AsTypeExprClass:
+ case Expr::ObjCIndirectCopyRestoreExprClass:
+ case Expr::MaterializeTemporaryExprClass:
return ICEDiag(2, E->getLocStart());
case Expr::SizeOfPackExprClass:
@@ -2778,6 +2807,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// GCC considers the GNU __null value to be an integral constant expression.
return NoDiag();
+ case Expr::SubstNonTypeTemplateParmExprClass:
+ return
+ CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx);
+
case Expr::ParenExprClass:
return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
case Expr::GenericSelectionExprClass:
@@ -2995,7 +3028,8 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXFunctionalCastExprClass:
case Expr::CXXStaticCastExprClass:
case Expr::CXXReinterpretCastExprClass:
- case Expr::CXXConstCastExprClass: {
+ case Expr::CXXConstCastExprClass:
+ case Expr::ObjCBridgedCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
if (SubExpr->getType()->isIntegralOrEnumerationType())
return CheckICE(SubExpr, Ctx);
diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp
index f428318a21e3..b96d65a729ca 100644
--- a/lib/AST/ExternalASTSource.cpp
+++ b/lib/AST/ExternalASTSource.cpp
@@ -51,11 +51,11 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
void ExternalASTSource::MaterializeVisibleDecls(const DeclContext *DC) { }
-bool
+ExternalLoadResult
ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
llvm::SmallVectorImpl<Decl*> &Result) {
- return true;
+ return ELR_AlreadyLoaded;
}
void ExternalASTSource::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { }
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index e81ec7e54b62..ec9863b298e6 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/SourceManager.h"
@@ -236,6 +237,9 @@ private:
bool mangleSubstitution(TemplateName Template);
bool mangleSubstitution(uintptr_t Ptr);
+ void mangleExistingSubstitution(QualType type);
+ void mangleExistingSubstitution(TemplateName name);
+
bool mangleStandardSubstitution(const NamedDecl *ND);
void addSubstitution(const NamedDecl *ND) {
@@ -255,9 +259,6 @@ private:
DeclarationName name,
unsigned KnownArity = UnknownArity);
- static bool isUnresolvedType(const Type *type);
- void mangleUnresolvedType(const Type *type);
-
void mangleName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
@@ -318,7 +319,7 @@ private:
unsigned NumTemplateArgs);
void mangleTemplateArgs(const TemplateParameterList &PL,
const TemplateArgumentList &AL);
- void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A);
+ void mangleTemplateArg(const NamedDecl *P, TemplateArgument A);
void mangleUnresolvedTemplateArgs(const TemplateArgument *args,
unsigned numArgs);
@@ -451,13 +452,8 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
FD = PrimaryTemplate->getTemplatedDecl();
}
- // Do the canonicalization out here because parameter types can
- // undergo additional canonicalization (e.g. array decay).
- const FunctionType *FT
- = cast<FunctionType>(Context.getASTContext()
- .getCanonicalType(FD->getType()));
-
- mangleBareFunctionType(FT, MangleReturnType);
+ mangleBareFunctionType(FD->getType()->getAs<FunctionType>(),
+ MangleReturnType);
}
static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
@@ -597,19 +593,13 @@ void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) {
if (mangleSubstitution(Template))
return;
- // FIXME: How to cope with operators here?
DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
assert(Dependent && "Not a dependent template name?");
- if (!Dependent->isIdentifier()) {
- // FIXME: We can't possibly know the arity of the operator here!
- Diagnostic &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
- "cannot mangle dependent operator name");
- Diags.Report(DiagID);
- return;
- }
+ if (const IdentifierInfo *Id = Dependent->getIdentifier())
+ mangleSourceName(Id);
+ else
+ mangleOperatorName(Dependent->getOperator(), UnknownArity);
- mangleSourceName(Dependent->getIdentifier());
addSubstitution(Template);
}
@@ -702,31 +692,6 @@ void CXXNameMangler::manglePrefix(QualType type) {
}
}
-/// Returns true if the given type, appearing within an
-/// unresolved-name, should be mangled as an unresolved-type.
-bool CXXNameMangler::isUnresolvedType(const Type *type) {
- // <unresolved-type> ::= <template-param>
- // ::= <decltype>
- // ::= <template-template-param> <template-args>
- // (this last is not official yet)
-
- if (isa<TemplateTypeParmType>(type)) return true;
- if (isa<DecltypeType>(type)) return true;
- // typeof?
- if (const TemplateSpecializationType *tst =
- dyn_cast<TemplateSpecializationType>(type)) {
- TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl();
- if (temp && isa<TemplateTemplateParmDecl>(temp))
- return true;
- }
- return false;
-}
-
-void CXXNameMangler::mangleUnresolvedType(const Type *type) {
- // This seems to be do everything we want.
- mangleType(QualType(type, 0));
-}
-
/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
///
/// \param firstQualifierLookup - the entity found by unqualified lookup
@@ -794,45 +759,141 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
} else {
// Otherwise, all the cases want this.
Out << "sr";
+ }
+
+ // Only certain other types are valid as prefixes; enumerate them.
+ switch (type->getTypeClass()) {
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Pointer:
+ case Type::BlockPointer:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::MemberPointer:
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ case Type::Enum:
+ case Type::Paren:
+ case Type::Elaborated:
+ case Type::Attributed:
+ case Type::Auto:
+ case Type::PackExpansion:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ llvm_unreachable("type is illegal as a nested name specifier");
+
+ case Type::SubstTemplateTypeParmPack:
+ // FIXME: not clear how to mangle this!
+ // template <class T...> class A {
+ // template <class U...> void foo(decltype(T::foo(U())) x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+
+ // <unresolved-type> ::= <template-param>
+ // ::= <decltype>
+ // ::= <template-template-param> <template-args>
+ // (this last is not official yet)
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::TemplateTypeParm:
+ case Type::UnaryTransform:
+ case Type::SubstTemplateTypeParm:
+ unresolvedType:
+ assert(!qualifier->getPrefix());
+
+ // We only get here recursively if we're followed by identifiers.
+ if (recursive) Out << 'N';
+
+ // This seems to do everything we want. It's not really
+ // sanctioned for a substituted template parameter, though.
+ mangleType(QualType(type, 0));
+
+ // We never want to print 'E' directly after an unresolved-type,
+ // so we return directly.
+ return;
+
+ case Type::Typedef:
+ mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
+ break;
+
+ case Type::UnresolvedUsing:
+ mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
+ ->getIdentifier());
+ break;
- if (isUnresolvedType(type)) {
- // We only get here recursively if we're followed by identifiers.
- if (recursive) Out << 'N';
- mangleUnresolvedType(type);
+ case Type::Record:
+ mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
+ break;
- // We never want to print 'E' directly after an unresolved-type,
- // so we return directly.
- return;
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *tst
+ = cast<TemplateSpecializationType>(type);
+ TemplateName name = tst->getTemplateName();
+ switch (name.getKind()) {
+ case TemplateName::Template:
+ case TemplateName::QualifiedTemplate: {
+ TemplateDecl *temp = name.getAsTemplateDecl();
+
+ // If the base is a template template parameter, this is an
+ // unresolved type.
+ assert(temp && "no template for template specialization type");
+ if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
+
+ mangleSourceName(temp->getIdentifier());
+ break;
}
- }
- assert(!isUnresolvedType(type));
+ case TemplateName::OverloadedTemplate:
+ case TemplateName::DependentTemplate:
+ llvm_unreachable("invalid base for a template specialization type");
+
+ case TemplateName::SubstTemplateTemplateParm: {
+ SubstTemplateTemplateParmStorage *subst
+ = name.getAsSubstTemplateTemplateParm();
+ mangleExistingSubstitution(subst->getReplacement());
+ break;
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ // FIXME: not clear how to mangle this!
+ // template <template <class U> class T...> class A {
+ // template <class U...> void foo(decltype(T<U>::foo) x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+ }
+ }
- // Only certain other types are valid as prefixes; enumerate them.
- // FIXME: can we get ElaboratedTypes here?
- // FIXME: SubstTemplateTypeParmType?
- if (const TagType *t = dyn_cast<TagType>(type)) {
- mangleSourceName(t->getDecl()->getIdentifier());
- } else if (const TypedefType *t = dyn_cast<TypedefType>(type)) {
- mangleSourceName(t->getDecl()->getIdentifier());
- } else if (const UnresolvedUsingType *t
- = dyn_cast<UnresolvedUsingType>(type)) {
- mangleSourceName(t->getDecl()->getIdentifier());
- } else if (const DependentNameType *t
- = dyn_cast<DependentNameType>(type)) {
- mangleSourceName(t->getIdentifier());
- } else if (const TemplateSpecializationType *tst
- = dyn_cast<TemplateSpecializationType>(type)) {
- TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl();
- assert(temp && "no template for template specialization type");
- mangleSourceName(temp->getIdentifier());
mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
- } else if (const DependentTemplateSpecializationType *tst
- = dyn_cast<DependentTemplateSpecializationType>(type)) {
+ break;
+ }
+
+ case Type::InjectedClassName:
+ mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
+ ->getIdentifier());
+ break;
+
+ case Type::DependentName:
+ mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
+ break;
+
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateSpecializationType *tst
+ = cast<DependentTemplateSpecializationType>(type);
mangleSourceName(tst->getIdentifier());
mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
- } else {
- llvm_unreachable("unexpected type in nested name specifier!");
+ break;
+ }
}
break;
}
@@ -1036,7 +1097,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
case DeclarationName::CXXConversionFunctionName:
// <operator-name> ::= cv <type> # (cast)
Out << "cv";
- mangleType(Context.getASTContext().getCanonicalType(Name.getCXXNameType()));
+ mangleType(Name.getCXXNameType());
break;
case DeclarationName::CXXOperatorName: {
@@ -1323,10 +1384,23 @@ void CXXNameMangler::mangleType(TemplateName TN) {
break;
}
+ case TemplateName::SubstTemplateTemplateParm: {
+ // Substituted template parameters are mangled as the substituted
+ // template. This will check for the substitution twice, which is
+ // fine, but we have to return early so that we don't try to *add*
+ // the substitution twice.
+ SubstTemplateTemplateParmStorage *subst
+ = TN.getAsSubstTemplateTemplateParm();
+ mangleType(subst->getReplacement());
+ return;
+ }
+
case TemplateName::SubstTemplateTemplateParmPack: {
- SubstTemplateTemplateParmPackStorage *SubstPack
- = TN.getAsSubstTemplateTemplateParmPack();
- mangleTemplateParameter(SubstPack->getParameterPack()->getIndex());
+ // FIXME: not clear how to mangle this!
+ // template <template <class> class T...> class A {
+ // template <template <class> class U...> void foo(B<T,U> x...);
+ // };
+ Out << "_SUBSTPACK_";
break;
}
}
@@ -1464,7 +1538,40 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
Out << 'U' << ASString.size() << ASString;
}
- // FIXME: For now, just drop all extension qualifiers on the floor.
+ llvm::StringRef LifetimeName;
+ switch (Quals.getObjCLifetime()) {
+ // Objective-C ARC Extension:
+ //
+ // <type> ::= U "__strong"
+ // <type> ::= U "__weak"
+ // <type> ::= U "__autoreleasing"
+ case Qualifiers::OCL_None:
+ break;
+
+ case Qualifiers::OCL_Weak:
+ LifetimeName = "__weak";
+ break;
+
+ case Qualifiers::OCL_Strong:
+ LifetimeName = "__strong";
+ break;
+
+ case Qualifiers::OCL_Autoreleasing:
+ LifetimeName = "__autoreleasing";
+ break;
+
+ case Qualifiers::OCL_ExplicitNone:
+ // The __unsafe_unretained qualifier is *not* mangled, so that
+ // __unsafe_unretained types in ARC produce the same manglings as the
+ // equivalent (but, naturally, unqualified) types in non-ARC, providing
+ // better ABI compatibility.
+ //
+ // It's safe to do this because unqualified 'id' won't show up
+ // in any type signatures that need to be mangled.
+ break;
+ }
+ if (!LifetimeName.empty())
+ Out << 'U' << LifetimeName.size() << LifetimeName;
}
void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
@@ -1489,26 +1596,59 @@ void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
Context.mangleObjCMethodName(MD, Out);
}
-void CXXNameMangler::mangleType(QualType nonCanon) {
- // Only operate on the canonical type!
- QualType canon = nonCanon.getCanonicalType();
-
- SplitQualType split = canon.split();
+void CXXNameMangler::mangleType(QualType T) {
+ // If our type is instantiation-dependent but not dependent, we mangle
+ // it as it was written in the source, removing any top-level sugar.
+ // Otherwise, use the canonical type.
+ //
+ // FIXME: This is an approximation of the instantiation-dependent name
+ // mangling rules, since we should really be using the type as written and
+ // augmented via semantic analysis (i.e., with implicit conversions and
+ // default template arguments) for any instantiation-dependent type.
+ // Unfortunately, that requires several changes to our AST:
+ // - Instantiation-dependent TemplateSpecializationTypes will need to be
+ // uniqued, so that we can handle substitutions properly
+ // - Default template arguments will need to be represented in the
+ // TemplateSpecializationType, since they need to be mangled even though
+ // they aren't written.
+ // - Conversions on non-type template arguments need to be expressed, since
+ // they can affect the mangling of sizeof/alignof.
+ if (!T->isInstantiationDependentType() || T->isDependentType())
+ T = T.getCanonicalType();
+ else {
+ // Desugar any types that are purely sugar.
+ do {
+ // Don't desugar through template specialization types that aren't
+ // type aliases. We need to mangle the template arguments as written.
+ if (const TemplateSpecializationType *TST
+ = dyn_cast<TemplateSpecializationType>(T))
+ if (!TST->isTypeAlias())
+ break;
+
+ QualType Desugared
+ = T.getSingleStepDesugaredType(Context.getASTContext());
+ if (Desugared == T)
+ break;
+
+ T = Desugared;
+ } while (true);
+ }
+ SplitQualType split = T.split();
Qualifiers quals = split.second;
const Type *ty = split.first;
- bool isSubstitutable = quals || !isa<BuiltinType>(ty);
- if (isSubstitutable && mangleSubstitution(canon))
+ bool isSubstitutable = quals || !isa<BuiltinType>(T);
+ if (isSubstitutable && mangleSubstitution(T))
return;
// If we're mangling a qualified array type, push the qualifiers to
// the element type.
- if (quals && isa<ArrayType>(ty)) {
- ty = Context.getASTContext().getAsArrayType(canon);
+ if (quals && isa<ArrayType>(T)) {
+ ty = Context.getASTContext().getAsArrayType(T);
quals = Qualifiers();
- // Note that we don't update canon: we want to add the
- // substitution at the canonical type.
+ // Note that we don't update T: we want to add the
+ // substitution at the original type.
}
if (quals) {
@@ -1533,7 +1673,7 @@ void CXXNameMangler::mangleType(QualType nonCanon) {
// Add the substitution.
if (isSubstitutable)
- addSubstitution(canon);
+ addSubstitution(T);
}
void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) {
@@ -1647,7 +1787,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
ArgEnd = Proto->arg_type_end();
Arg != ArgEnd; ++Arg)
- mangleType(*Arg);
+ mangleType(Context.getASTContext().getSignatureParameterType(*Arg));
FunctionTypeDepth.pop(saved);
@@ -1737,7 +1877,11 @@ void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
// <type> ::= <template-param>
void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {
- mangleTemplateParameter(T->getReplacedParameter()->getIndex());
+ // FIXME: not clear how to mangle this!
+ // template <class T...> class A {
+ // template <class U...> void foo(T(*)(U) x...);
+ // };
+ Out << "_SUBSTPACK_";
}
// <type> ::= P <type> # pointer-to
@@ -2052,6 +2196,9 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// <expr-primary> ::= L <type> <value number> E # integer literal
// ::= L <type <value float> E # floating literal
// ::= L <mangled-name> E # external name
+ QualType ImplicitlyConvertedToType;
+
+recurse:
switch (E->getStmtClass()) {
case Expr::NoStmtClass:
#define ABSTRACT_STMT(Type)
@@ -2089,6 +2236,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
case Expr::ObjCProtocolExprClass:
case Expr::ObjCSelectorExprClass:
case Expr::ObjCStringLiteralClass:
+ case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::OffsetOfExprClass:
case Expr::PredefinedExprClass:
case Expr::ShuffleVectorExprClass:
@@ -2131,6 +2279,11 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
break;
+ case Expr::SubstNonTypeTemplateParmExprClass:
+ mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
+ Arity);
+ break;
+
case Expr::CXXMemberCallExprClass: // fallthrough
case Expr::CallExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
@@ -2209,6 +2362,10 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
mangleUnresolvedName(ULE->getQualifier(), 0, ULE->getName(), Arity);
+
+ // All the <unresolved-name> productions end in a
+ // base-unresolved-name, where <template-args> are just tacked
+ // onto the end.
if (ULE->hasExplicitTemplateArgs())
mangleTemplateArgs(ULE->getExplicitTemplateArgs());
break;
@@ -2241,6 +2398,23 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
case Expr::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
+
+ if (!SAE->isInstantiationDependent()) {
+ // Itanium C++ ABI:
+ // If the operand of a sizeof or alignof operator is not
+ // instantiation-dependent it is encoded as an integer literal
+ // reflecting the result of the operator.
+ //
+ // If the result of the operator is implicitly converted to a known
+ // integer type, that type is used for the literal; otherwise, the type
+ // of std::size_t or std::ptrdiff_t is used.
+ QualType T = (ImplicitlyConvertedToType.isNull() ||
+ !ImplicitlyConvertedToType->isIntegerType())? SAE->getType()
+ : ImplicitlyConvertedToType;
+ mangleIntegerLiteral(T, SAE->EvaluateAsInt(Context.getASTContext()));
+ break;
+ }
+
switch(SAE->getKind()) {
case UETT_SizeOf:
Out << 's';
@@ -2344,10 +2518,19 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
}
case Expr::ImplicitCastExprClass: {
- mangleExpression(cast<ImplicitCastExpr>(E)->getSubExpr(), Arity);
- break;
+ ImplicitlyConvertedToType = E->getType();
+ E = cast<ImplicitCastExpr>(E)->getSubExpr();
+ goto recurse;
}
-
+
+ case Expr::ObjCBridgedCastExprClass: {
+ // Mangle ownership casts as a vendor extended operator __bridge,
+ // __bridge_transfer, or __bridge_retain.
+ llvm::StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
+ Out << "v1U" << Kind.size() << Kind;
+ }
+ // Fall through to mangle the cast itself.
+
case Expr::CStyleCastExprClass:
case Expr::CXXStaticCastExprClass:
case Expr::CXXDynamicCastExprClass:
@@ -2408,35 +2591,22 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
}
case Expr::SubstNonTypeTemplateParmPackExprClass:
- mangleTemplateParameter(
- cast<SubstNonTypeTemplateParmPackExpr>(E)->getParameterPack()->getIndex());
+ // FIXME: not clear how to mangle this!
+ // template <unsigned N...> class A {
+ // template <class U...> void foo(U (&x)[N]...);
+ // };
+ Out << "_SUBSTPACK_";
break;
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
- NestedNameSpecifier *NNS = DRE->getQualifier();
- const Type *QTy = NNS->getAsType();
-
- // When we're dealing with a nested-name-specifier that has just a
- // dependent identifier in it, mangle that as a typename. FIXME:
- // It isn't clear that we ever actually want to have such a
- // nested-name-specifier; why not just represent it as a typename type?
- if (!QTy && NNS->getAsIdentifier() && NNS->getPrefix()) {
- QTy = getASTContext().getDependentNameType(ETK_Typename,
- NNS->getPrefix(),
- NNS->getAsIdentifier())
- .getTypePtr();
- }
- assert(QTy && "Qualifier was not type!");
+ mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity);
- // ::= sr <type> <unqualified-name> # dependent name
- // ::= sr <type> <unqualified-name> <template-args> # dependent template-id
- Out << "sr";
- mangleType(QualType(QTy, 0));
- mangleUnqualifiedName(0, DRE->getDeclName(), Arity);
+ // All the <unresolved-name> productions end in a
+ // base-unresolved-name, where <template-args> are just tacked
+ // onto the end.
if (DRE->hasExplicitTemplateArgs())
mangleTemplateArgs(DRE->getExplicitTemplateArgs());
-
break;
}
@@ -2537,15 +2707,13 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
else if (const TemplateTemplateParmDecl *TempTP
= dyn_cast<TemplateTemplateParmDecl>(Pack))
mangleTemplateParameter(TempTP->getIndex());
- else {
- // Note: proposed by Mike Herrick on 11/30/10
- // <expression> ::= sZ <function-param> # size of function parameter pack
- Diagnostic &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
- "cannot mangle sizeof...(function parameter pack)");
- Diags.Report(DiagID);
- return;
- }
+ else
+ mangleFunctionParam(cast<ParmVarDecl>(Pack));
+ break;
+ }
+
+ case Expr::MaterializeTemporaryExprClass: {
+ mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
break;
}
}
@@ -2696,12 +2864,15 @@ void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
}
void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
- const TemplateArgument &A) {
+ TemplateArgument A) {
// <template-arg> ::= <type> # type or template
// ::= X <expression> E # expression
// ::= <expr-primary> # simple expressions
// ::= J <template-arg>* E # argument pack
- // ::= sp <expression> # pack expansion of (C++0x)
+ // ::= sp <expression> # pack expansion of (C++0x)
+ if (!A.isInstantiationDependent() || A.isDependent())
+ A = Context.getASTContext().getCanonicalTemplateArgument(A);
+
switch (A.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Cannot mangle NULL template argument");
@@ -2780,6 +2951,18 @@ void CXXNameMangler::mangleTemplateParameter(unsigned Index) {
Out << 'T' << (Index - 1) << '_';
}
+void CXXNameMangler::mangleExistingSubstitution(QualType type) {
+ bool result = mangleSubstitution(type);
+ assert(result && "no existing substitution for type");
+ (void) result;
+}
+
+void CXXNameMangler::mangleExistingSubstitution(TemplateName tname) {
+ bool result = mangleSubstitution(tname);
+ assert(result && "no existing substitution for template name");
+ (void) result;
+}
+
// <substitution> ::= S <seq-id> _
// ::= S_
bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index 2878dff3edc4..f6d4f2513ce4 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -174,6 +174,28 @@ bool NestedNameSpecifier::isDependent() const {
return false;
}
+/// \brief Whether this nested name specifier refers to a dependent
+/// type or not.
+bool NestedNameSpecifier::isInstantiationDependent() const {
+ switch (getKind()) {
+ case Identifier:
+ // Identifier specifiers always represent dependent types
+ return true;
+
+ case Namespace:
+ case NamespaceAlias:
+ case Global:
+ return false;
+
+ case TypeSpec:
+ case TypeSpecWithTemplate:
+ return getAsType()->isInstantiationDependentType();
+ }
+
+ // Necessary to suppress a GCC warning.
+ return false;
+}
+
bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
switch (getKind()) {
case Identifier:
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index eca351aec8dd..b7b2005e9f84 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -66,6 +66,15 @@ Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
return S;
}
+Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
+ Stmt *Paren = 0;
+ while (isa<ParenExpr>(S)) {
+ Paren = S;
+ S = getParent(S);
+ };
+ return Paren;
+}
+
bool ParentMap::isConsumedExpr(Expr* E) const {
Stmt *P = getParent(E);
Stmt *DirectChild = E;
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index de0b1d0ed9db..5636a6f0f64a 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -1242,12 +1242,11 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
}
InitializeLayout(D);
-
+ ObjCInterfaceDecl *OI = const_cast<ObjCInterfaceDecl*>(D);
// Layout each ivar sequentially.
- llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
- Context.ShallowCollectObjCIvars(D, Ivars);
- for (unsigned i = 0, e = Ivars.size(); i != e; ++i)
- LayoutField(Ivars[i]);
+ for (ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
+ IVD; IVD = IVD->getNextIvar())
+ LayoutField(IVD);
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 380ad94ca224..fd6f21d43b59 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -20,7 +20,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
-#include <cstdio>
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
static struct StmtClassNameTable {
@@ -54,23 +54,24 @@ void Stmt::PrintStats() {
getStmtInfoTableEntry(Stmt::NullStmtClass);
unsigned sum = 0;
- fprintf(stderr, "*** Stmt/Expr Stats:\n");
+ llvm::errs() << "\n*** Stmt/Expr Stats:\n";
for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
if (StmtClassInfo[i].Name == 0) continue;
sum += StmtClassInfo[i].Counter;
}
- fprintf(stderr, " %d stmts/exprs total.\n", sum);
+ llvm::errs() << " " << sum << " stmts/exprs total.\n";
sum = 0;
for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
if (StmtClassInfo[i].Name == 0) continue;
if (StmtClassInfo[i].Counter == 0) continue;
- fprintf(stderr, " %d %s, %d each (%d bytes)\n",
- StmtClassInfo[i].Counter, StmtClassInfo[i].Name,
- StmtClassInfo[i].Size,
- StmtClassInfo[i].Counter*StmtClassInfo[i].Size);
+ llvm::errs() << " " << StmtClassInfo[i].Counter << " "
+ << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size
+ << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size
+ << " bytes)\n";
sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
}
- fprintf(stderr, "Total bytes = %d\n", sum);
+
+ llvm::errs() << "Total bytes = " << sum << "\n";
}
void Stmt::addStmtClass(StmtClass s) {
@@ -84,6 +85,18 @@ bool Stmt::CollectingStats(bool Enable) {
return StatSwitch;
}
+Stmt *Stmt::IgnoreImplicit() {
+ Stmt *s = this;
+
+ if (ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(s))
+ s = ewc->getSubExpr();
+
+ while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(s))
+ s = ice->getSubExpr();
+
+ return s;
+}
+
namespace {
struct good {};
struct bad {};
@@ -365,6 +378,10 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
// Handle %x4 and %x[foo] by capturing x as the modifier character.
char Modifier = '\0';
if (isalpha(EscapedChar)) {
+ if (CurPtr == StrEnd) { // Premature end.
+ DiagOffs = CurPtr-StrStart-1;
+ return diag::err_asm_invalid_escape;
+ }
Modifier = EscapedChar;
EscapedChar = *CurPtr++;
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 87588e451884..f705a84c7cf4 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -449,6 +449,12 @@ void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) {
OS << "\n";
}
+void StmtPrinter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *Node) {
+ Indent() << "@autoreleasepool";
+ PrintRawCompoundStmt(dyn_cast<CompoundStmt>(Node->getSubStmt()));
+ OS << "\n";
+}
+
void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) {
OS << "catch (";
if (Decl *ExDecl = Node->getExceptionDecl())
@@ -1407,6 +1413,15 @@ void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
OS << Node->getParameterPack()->getNameAsString();
}
+void StmtPrinter::VisitSubstNonTypeTemplateParmExpr(
+ SubstNonTypeTemplateParmExpr *Node) {
+ Visit(Node->getReplacement());
+}
+
+void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
+ PrintExpr(Node->GetTemporaryExpr());
+}
+
// Obj-C
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
@@ -1464,6 +1479,17 @@ void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
OS << "]";
}
+void
+StmtPrinter::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) {
+ PrintExpr(E->getSubExpr());
+}
+
+void
+StmtPrinter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
+ OS << "(" << E->getBridgeKindName() << E->getType().getAsString(Policy)
+ << ")";
+ PrintExpr(E->getSubExpr());
+}
void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
BlockDecl *BD = Node->getBlockDecl();
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index b117cd9a525f..120c9e50a92a 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -23,7 +23,7 @@
using namespace clang;
namespace {
- class StmtProfiler : public StmtVisitor<StmtProfiler> {
+ class StmtProfiler : public ConstStmtVisitor<StmtProfiler> {
llvm::FoldingSetNodeID &ID;
const ASTContext &Context;
bool Canonical;
@@ -33,14 +33,14 @@ namespace {
bool Canonical)
: ID(ID), Context(Context), Canonical(Canonical) { }
- void VisitStmt(Stmt *S);
+ void VisitStmt(const Stmt *S);
-#define STMT(Node, Base) void Visit##Node(Node *S);
+#define STMT(Node, Base) void Visit##Node(const Node *S);
#include "clang/AST/StmtNodes.inc"
/// \brief Visit a declaration that is referenced within an expression
/// or statement.
- void VisitDecl(Decl *D);
+ void VisitDecl(const Decl *D);
/// \brief Visit a type that is referenced within an expression or
/// statement.
@@ -59,96 +59,97 @@ namespace {
/// \brief Visit template arguments that occur within an expression or
/// statement.
- void VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs);
+ void VisitTemplateArguments(const TemplateArgumentLoc *Args,
+ unsigned NumArgs);
/// \brief Visit a single template argument.
void VisitTemplateArgument(const TemplateArgument &Arg);
};
}
-void StmtProfiler::VisitStmt(Stmt *S) {
+void StmtProfiler::VisitStmt(const Stmt *S) {
ID.AddInteger(S->getStmtClass());
- for (Stmt::child_range C = S->children(); C; ++C)
+ for (Stmt::const_child_range C = S->children(); C; ++C)
Visit(*C);
}
-void StmtProfiler::VisitDeclStmt(DeclStmt *S) {
+void StmtProfiler::VisitDeclStmt(const DeclStmt *S) {
VisitStmt(S);
- for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ for (DeclStmt::const_decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D)
VisitDecl(*D);
}
-void StmtProfiler::VisitNullStmt(NullStmt *S) {
+void StmtProfiler::VisitNullStmt(const NullStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitCompoundStmt(CompoundStmt *S) {
+void StmtProfiler::VisitCompoundStmt(const CompoundStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitSwitchCase(SwitchCase *S) {
+void StmtProfiler::VisitSwitchCase(const SwitchCase *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitCaseStmt(CaseStmt *S) {
+void StmtProfiler::VisitCaseStmt(const CaseStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitDefaultStmt(DefaultStmt *S) {
+void StmtProfiler::VisitDefaultStmt(const DefaultStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitLabelStmt(LabelStmt *S) {
+void StmtProfiler::VisitLabelStmt(const LabelStmt *S) {
VisitStmt(S);
VisitDecl(S->getDecl());
}
-void StmtProfiler::VisitIfStmt(IfStmt *S) {
+void StmtProfiler::VisitIfStmt(const IfStmt *S) {
VisitStmt(S);
VisitDecl(S->getConditionVariable());
}
-void StmtProfiler::VisitSwitchStmt(SwitchStmt *S) {
+void StmtProfiler::VisitSwitchStmt(const SwitchStmt *S) {
VisitStmt(S);
VisitDecl(S->getConditionVariable());
}
-void StmtProfiler::VisitWhileStmt(WhileStmt *S) {
+void StmtProfiler::VisitWhileStmt(const WhileStmt *S) {
VisitStmt(S);
VisitDecl(S->getConditionVariable());
}
-void StmtProfiler::VisitDoStmt(DoStmt *S) {
+void StmtProfiler::VisitDoStmt(const DoStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitForStmt(ForStmt *S) {
+void StmtProfiler::VisitForStmt(const ForStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitGotoStmt(GotoStmt *S) {
+void StmtProfiler::VisitGotoStmt(const GotoStmt *S) {
VisitStmt(S);
VisitDecl(S->getLabel());
}
-void StmtProfiler::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+void StmtProfiler::VisitIndirectGotoStmt(const IndirectGotoStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitContinueStmt(ContinueStmt *S) {
+void StmtProfiler::VisitContinueStmt(const ContinueStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitBreakStmt(BreakStmt *S) {
+void StmtProfiler::VisitBreakStmt(const BreakStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitReturnStmt(ReturnStmt *S) {
+void StmtProfiler::VisitReturnStmt(const ReturnStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitAsmStmt(AsmStmt *S) {
+void StmtProfiler::VisitAsmStmt(const AsmStmt *S) {
VisitStmt(S);
ID.AddBoolean(S->isVolatile());
ID.AddBoolean(S->isSimple());
@@ -168,63 +169,69 @@ void StmtProfiler::VisitAsmStmt(AsmStmt *S) {
VisitStringLiteral(S->getClobber(I));
}
-void StmtProfiler::VisitCXXCatchStmt(CXXCatchStmt *S) {
+void StmtProfiler::VisitCXXCatchStmt(const CXXCatchStmt *S) {
VisitStmt(S);
VisitType(S->getCaughtType());
}
-void StmtProfiler::VisitCXXTryStmt(CXXTryStmt *S) {
+void StmtProfiler::VisitCXXTryStmt(const CXXTryStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
+void StmtProfiler::VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitSEHTryStmt(SEHTryStmt *S) {
+void StmtProfiler::VisitSEHTryStmt(const SEHTryStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitSEHFinallyStmt(SEHFinallyStmt *S) {
+void StmtProfiler::VisitSEHFinallyStmt(const SEHFinallyStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitSEHExceptStmt(SEHExceptStmt *S) {
+void StmtProfiler::VisitSEHExceptStmt(const SEHExceptStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+void StmtProfiler::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+void StmtProfiler::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *S) {
VisitStmt(S);
ID.AddBoolean(S->hasEllipsis());
if (S->getCatchParamDecl())
VisitType(S->getCatchParamDecl()->getType());
}
-void StmtProfiler::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+void StmtProfiler::VisitObjCAtFinallyStmt(const ObjCAtFinallyStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+void StmtProfiler::VisitObjCAtTryStmt(const ObjCAtTryStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+void
+StmtProfiler::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+void StmtProfiler::VisitObjCAtThrowStmt(const ObjCAtThrowStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitExpr(Expr *S) {
+void
+StmtProfiler::VisitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) {
+void StmtProfiler::VisitExpr(const Expr *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
VisitExpr(S);
if (!Canonical)
VisitNestedNameSpecifier(S->getQualifier());
@@ -233,52 +240,52 @@ void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) {
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
-void StmtProfiler::VisitPredefinedExpr(PredefinedExpr *S) {
+void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
VisitExpr(S);
ID.AddInteger(S->getIdentType());
}
-void StmtProfiler::VisitIntegerLiteral(IntegerLiteral *S) {
+void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) {
VisitExpr(S);
S->getValue().Profile(ID);
}
-void StmtProfiler::VisitCharacterLiteral(CharacterLiteral *S) {
+void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) {
VisitExpr(S);
ID.AddBoolean(S->isWide());
ID.AddInteger(S->getValue());
}
-void StmtProfiler::VisitFloatingLiteral(FloatingLiteral *S) {
+void StmtProfiler::VisitFloatingLiteral(const FloatingLiteral *S) {
VisitExpr(S);
S->getValue().Profile(ID);
ID.AddBoolean(S->isExact());
}
-void StmtProfiler::VisitImaginaryLiteral(ImaginaryLiteral *S) {
+void StmtProfiler::VisitImaginaryLiteral(const ImaginaryLiteral *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitStringLiteral(StringLiteral *S) {
+void StmtProfiler::VisitStringLiteral(const StringLiteral *S) {
VisitExpr(S);
ID.AddString(S->getString());
ID.AddBoolean(S->isWide());
}
-void StmtProfiler::VisitParenExpr(ParenExpr *S) {
+void StmtProfiler::VisitParenExpr(const ParenExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitParenListExpr(ParenListExpr *S) {
+void StmtProfiler::VisitParenListExpr(const ParenListExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitUnaryOperator(UnaryOperator *S) {
+void StmtProfiler::VisitUnaryOperator(const UnaryOperator *S) {
VisitExpr(S);
ID.AddInteger(S->getOpcode());
}
-void StmtProfiler::VisitOffsetOfExpr(OffsetOfExpr *S) {
+void StmtProfiler::VisitOffsetOfExpr(const OffsetOfExpr *S) {
VisitType(S->getTypeSourceInfo()->getType());
unsigned n = S->getNumComponents();
for (unsigned i = 0; i < n; ++i) {
@@ -306,22 +313,23 @@ void StmtProfiler::VisitOffsetOfExpr(OffsetOfExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *S) {
+void
+StmtProfiler::VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *S) {
VisitExpr(S);
ID.AddInteger(S->getKind());
if (S->isArgumentType())
VisitType(S->getArgumentType());
}
-void StmtProfiler::VisitArraySubscriptExpr(ArraySubscriptExpr *S) {
+void StmtProfiler::VisitArraySubscriptExpr(const ArraySubscriptExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitCallExpr(CallExpr *S) {
+void StmtProfiler::VisitCallExpr(const CallExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitMemberExpr(MemberExpr *S) {
+void StmtProfiler::VisitMemberExpr(const MemberExpr *S) {
VisitExpr(S);
VisitDecl(S->getMemberDecl());
if (!Canonical)
@@ -329,72 +337,74 @@ void StmtProfiler::VisitMemberExpr(MemberExpr *S) {
ID.AddBoolean(S->isArrow());
}
-void StmtProfiler::VisitCompoundLiteralExpr(CompoundLiteralExpr *S) {
+void StmtProfiler::VisitCompoundLiteralExpr(const CompoundLiteralExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isFileScope());
}
-void StmtProfiler::VisitCastExpr(CastExpr *S) {
+void StmtProfiler::VisitCastExpr(const CastExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitImplicitCastExpr(ImplicitCastExpr *S) {
+void StmtProfiler::VisitImplicitCastExpr(const ImplicitCastExpr *S) {
VisitCastExpr(S);
ID.AddInteger(S->getValueKind());
}
-void StmtProfiler::VisitExplicitCastExpr(ExplicitCastExpr *S) {
+void StmtProfiler::VisitExplicitCastExpr(const ExplicitCastExpr *S) {
VisitCastExpr(S);
VisitType(S->getTypeAsWritten());
}
-void StmtProfiler::VisitCStyleCastExpr(CStyleCastExpr *S) {
+void StmtProfiler::VisitCStyleCastExpr(const CStyleCastExpr *S) {
VisitExplicitCastExpr(S);
}
-void StmtProfiler::VisitBinaryOperator(BinaryOperator *S) {
+void StmtProfiler::VisitBinaryOperator(const BinaryOperator *S) {
VisitExpr(S);
ID.AddInteger(S->getOpcode());
}
-void StmtProfiler::VisitCompoundAssignOperator(CompoundAssignOperator *S) {
+void
+StmtProfiler::VisitCompoundAssignOperator(const CompoundAssignOperator *S) {
VisitBinaryOperator(S);
}
-void StmtProfiler::VisitConditionalOperator(ConditionalOperator *S) {
+void StmtProfiler::VisitConditionalOperator(const ConditionalOperator *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitBinaryConditionalOperator(BinaryConditionalOperator *S){
+void StmtProfiler::VisitBinaryConditionalOperator(
+ const BinaryConditionalOperator *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitAddrLabelExpr(AddrLabelExpr *S) {
+void StmtProfiler::VisitAddrLabelExpr(const AddrLabelExpr *S) {
VisitExpr(S);
VisitDecl(S->getLabel());
}
-void StmtProfiler::VisitStmtExpr(StmtExpr *S) {
+void StmtProfiler::VisitStmtExpr(const StmtExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitShuffleVectorExpr(ShuffleVectorExpr *S) {
+void StmtProfiler::VisitShuffleVectorExpr(const ShuffleVectorExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitChooseExpr(ChooseExpr *S) {
+void StmtProfiler::VisitChooseExpr(const ChooseExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitGNUNullExpr(GNUNullExpr *S) {
+void StmtProfiler::VisitGNUNullExpr(const GNUNullExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitVAArgExpr(VAArgExpr *S) {
+void StmtProfiler::VisitVAArgExpr(const VAArgExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitInitListExpr(InitListExpr *S) {
+void StmtProfiler::VisitInitListExpr(const InitListExpr *S) {
if (S->getSyntacticForm()) {
VisitInitListExpr(S->getSyntacticForm());
return;
@@ -403,11 +413,11 @@ void StmtProfiler::VisitInitListExpr(InitListExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitDesignatedInitExpr(DesignatedInitExpr *S) {
+void StmtProfiler::VisitDesignatedInitExpr(const DesignatedInitExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->usesGNUSyntax());
- for (DesignatedInitExpr::designators_iterator D = S->designators_begin(),
- DEnd = S->designators_end();
+ for (DesignatedInitExpr::const_designators_iterator D =
+ S->designators_begin(), DEnd = S->designators_end();
D != DEnd; ++D) {
if (D->isFieldDesignator()) {
ID.AddInteger(0);
@@ -425,28 +435,28 @@ void StmtProfiler::VisitDesignatedInitExpr(DesignatedInitExpr *S) {
}
}
-void StmtProfiler::VisitImplicitValueInitExpr(ImplicitValueInitExpr *S) {
+void StmtProfiler::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitExtVectorElementExpr(ExtVectorElementExpr *S) {
+void StmtProfiler::VisitExtVectorElementExpr(const ExtVectorElementExpr *S) {
VisitExpr(S);
VisitName(&S->getAccessor());
}
-void StmtProfiler::VisitBlockExpr(BlockExpr *S) {
+void StmtProfiler::VisitBlockExpr(const BlockExpr *S) {
VisitExpr(S);
VisitDecl(S->getBlockDecl());
}
-void StmtProfiler::VisitBlockDeclRefExpr(BlockDeclRefExpr *S) {
+void StmtProfiler::VisitBlockDeclRefExpr(const BlockDeclRefExpr *S) {
VisitExpr(S);
VisitDecl(S->getDecl());
ID.AddBoolean(S->isByRef());
ID.AddBoolean(S->isConstQualAdded());
}
-void StmtProfiler::VisitGenericSelectionExpr(GenericSelectionExpr *S) {
+void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) {
VisitExpr(S);
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
QualType T = S->getAssocType(i);
@@ -458,7 +468,7 @@ void StmtProfiler::VisitGenericSelectionExpr(GenericSelectionExpr *S) {
}
}
-static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
+static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
UnaryOperatorKind &UnaryOp,
BinaryOperatorKind &BinaryOp) {
switch (S->getOperator()) {
@@ -645,7 +655,7 @@ static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
}
-void StmtProfiler::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
+void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
if (S->isTypeDependent()) {
// Type-dependent operator calls are profiled like their underlying
// syntactic operator.
@@ -671,97 +681,100 @@ void StmtProfiler::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
ID.AddInteger(S->getOperator());
}
-void StmtProfiler::VisitCXXMemberCallExpr(CXXMemberCallExpr *S) {
+void StmtProfiler::VisitCXXMemberCallExpr(const CXXMemberCallExpr *S) {
VisitCallExpr(S);
}
-void StmtProfiler::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *S) {
+void StmtProfiler::VisitCUDAKernelCallExpr(const CUDAKernelCallExpr *S) {
VisitCallExpr(S);
}
-void StmtProfiler::VisitAsTypeExpr(AsTypeExpr *S) {
+void StmtProfiler::VisitAsTypeExpr(const AsTypeExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitCXXNamedCastExpr(CXXNamedCastExpr *S) {
+void StmtProfiler::VisitCXXNamedCastExpr(const CXXNamedCastExpr *S) {
VisitExplicitCastExpr(S);
}
-void StmtProfiler::VisitCXXStaticCastExpr(CXXStaticCastExpr *S) {
+void StmtProfiler::VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
VisitCXXNamedCastExpr(S);
}
-void StmtProfiler::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *S) {
+void StmtProfiler::VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *S) {
VisitCXXNamedCastExpr(S);
}
-void StmtProfiler::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *S) {
+void
+StmtProfiler::VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *S) {
VisitCXXNamedCastExpr(S);
}
-void StmtProfiler::VisitCXXConstCastExpr(CXXConstCastExpr *S) {
+void StmtProfiler::VisitCXXConstCastExpr(const CXXConstCastExpr *S) {
VisitCXXNamedCastExpr(S);
}
-void StmtProfiler::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) {
+void StmtProfiler::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->getValue());
}
-void StmtProfiler::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) {
+void StmtProfiler::VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitCXXTypeidExpr(CXXTypeidExpr *S) {
+void StmtProfiler::VisitCXXTypeidExpr(const CXXTypeidExpr *S) {
VisitExpr(S);
if (S->isTypeOperand())
VisitType(S->getTypeOperand());
}
-void StmtProfiler::VisitCXXUuidofExpr(CXXUuidofExpr *S) {
+void StmtProfiler::VisitCXXUuidofExpr(const CXXUuidofExpr *S) {
VisitExpr(S);
if (S->isTypeOperand())
VisitType(S->getTypeOperand());
}
-void StmtProfiler::VisitCXXThisExpr(CXXThisExpr *S) {
+void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitCXXThrowExpr(CXXThrowExpr *S) {
+void StmtProfiler::VisitCXXThrowExpr(const CXXThrowExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *S) {
+void StmtProfiler::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {
VisitExpr(S);
VisitDecl(S->getParam());
}
-void StmtProfiler::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *S) {
+void StmtProfiler::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
VisitExpr(S);
VisitDecl(
const_cast<CXXDestructorDecl *>(S->getTemporary()->getDestructor()));
}
-void StmtProfiler::VisitCXXConstructExpr(CXXConstructExpr *S) {
+void StmtProfiler::VisitCXXConstructExpr(const CXXConstructExpr *S) {
VisitExpr(S);
VisitDecl(S->getConstructor());
ID.AddBoolean(S->isElidable());
}
-void StmtProfiler::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *S) {
+void StmtProfiler::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
VisitExplicitCastExpr(S);
}
-void StmtProfiler::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *S) {
+void
+StmtProfiler::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
VisitCXXConstructExpr(S);
}
-void StmtProfiler::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *S) {
+void
+StmtProfiler::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitCXXDeleteExpr(CXXDeleteExpr *S) {
+void StmtProfiler::VisitCXXDeleteExpr(const CXXDeleteExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isGlobalDelete());
ID.AddBoolean(S->isArrayForm());
@@ -769,7 +782,7 @@ void StmtProfiler::VisitCXXDeleteExpr(CXXDeleteExpr *S) {
}
-void StmtProfiler::VisitCXXNewExpr(CXXNewExpr *S) {
+void StmtProfiler::VisitCXXNewExpr(const CXXNewExpr *S) {
VisitExpr(S);
VisitType(S->getAllocatedType());
VisitDecl(S->getOperatorNew());
@@ -783,14 +796,15 @@ void StmtProfiler::VisitCXXNewExpr(CXXNewExpr *S) {
ID.AddInteger(S->getNumConstructorArgs());
}
-void StmtProfiler::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *S) {
+void
+StmtProfiler::VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isArrow());
VisitNestedNameSpecifier(S->getQualifier());
VisitType(S->getDestroyedType());
}
-void StmtProfiler::VisitOverloadExpr(OverloadExpr *S) {
+void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) {
VisitExpr(S);
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getName());
@@ -801,37 +815,37 @@ void StmtProfiler::VisitOverloadExpr(OverloadExpr *S) {
}
void
-StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
+StmtProfiler::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *S) {
VisitOverloadExpr(S);
}
-void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
+void StmtProfiler::VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *S) {
VisitExpr(S);
ID.AddInteger(S->getTrait());
VisitType(S->getQueriedType());
}
-void StmtProfiler::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *S) {
+void StmtProfiler::VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *S) {
VisitExpr(S);
ID.AddInteger(S->getTrait());
VisitType(S->getLhsType());
VisitType(S->getRhsType());
}
-void StmtProfiler::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *S) {
+void StmtProfiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *S) {
VisitExpr(S);
ID.AddInteger(S->getTrait());
VisitType(S->getQueriedType());
}
-void StmtProfiler::VisitExpressionTraitExpr(ExpressionTraitExpr *S) {
+void StmtProfiler::VisitExpressionTraitExpr(const ExpressionTraitExpr *S) {
VisitExpr(S);
ID.AddInteger(S->getTrait());
VisitExpr(S->getQueriedExpression());
}
-void
-StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
+void StmtProfiler::VisitDependentScopeDeclRefExpr(
+ const DependentScopeDeclRefExpr *S) {
VisitExpr(S);
VisitName(S->getDeclName());
VisitNestedNameSpecifier(S->getQualifier());
@@ -840,18 +854,18 @@ StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
-void StmtProfiler::VisitExprWithCleanups(ExprWithCleanups *S) {
+void StmtProfiler::VisitExprWithCleanups(const ExprWithCleanups *S) {
VisitExpr(S);
}
-void
-StmtProfiler::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *S) {
+void StmtProfiler::VisitCXXUnresolvedConstructExpr(
+ const CXXUnresolvedConstructExpr *S) {
VisitExpr(S);
VisitType(S->getTypeAsWritten());
}
-void
-StmtProfiler::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *S) {
+void StmtProfiler::VisitCXXDependentScopeMemberExpr(
+ const CXXDependentScopeMemberExpr *S) {
ID.AddBoolean(S->isImplicitAccess());
if (!S->isImplicitAccess()) {
VisitExpr(S);
@@ -864,7 +878,7 @@ StmtProfiler::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *S) {
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
-void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) {
+void StmtProfiler::VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *S) {
ID.AddBoolean(S->isImplicitAccess());
if (!S->isImplicitAccess()) {
VisitExpr(S);
@@ -877,57 +891,68 @@ void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) {
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
-void StmtProfiler::VisitCXXNoexceptExpr(CXXNoexceptExpr *S) {
+void StmtProfiler::VisitCXXNoexceptExpr(const CXXNoexceptExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitPackExpansionExpr(PackExpansionExpr *S) {
+void StmtProfiler::VisitPackExpansionExpr(const PackExpansionExpr *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitSizeOfPackExpr(SizeOfPackExpr *S) {
+void StmtProfiler::VisitSizeOfPackExpr(const SizeOfPackExpr *S) {
VisitExpr(S);
VisitDecl(S->getPack());
}
void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr(
- SubstNonTypeTemplateParmPackExpr *S) {
+ const SubstNonTypeTemplateParmPackExpr *S) {
VisitExpr(S);
VisitDecl(S->getParameterPack());
VisitTemplateArgument(S->getArgumentPack());
}
-void StmtProfiler::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+void StmtProfiler::VisitSubstNonTypeTemplateParmExpr(
+ const SubstNonTypeTemplateParmExpr *E) {
+ // Profile exactly as the replacement expression.
+ Visit(E->getReplacement());
+}
+
+void StmtProfiler::VisitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
VisitExpr(E);
}
-void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) {
+void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) {
VisitExpr(S);
}
-void StmtProfiler::VisitObjCEncodeExpr(ObjCEncodeExpr *S) {
+void StmtProfiler::VisitObjCEncodeExpr(const ObjCEncodeExpr *S) {
VisitExpr(S);
VisitType(S->getEncodedType());
}
-void StmtProfiler::VisitObjCSelectorExpr(ObjCSelectorExpr *S) {
+void StmtProfiler::VisitObjCSelectorExpr(const ObjCSelectorExpr *S) {
VisitExpr(S);
VisitName(S->getSelector());
}
-void StmtProfiler::VisitObjCProtocolExpr(ObjCProtocolExpr *S) {
+void StmtProfiler::VisitObjCProtocolExpr(const ObjCProtocolExpr *S) {
VisitExpr(S);
VisitDecl(S->getProtocol());
}
-void StmtProfiler::VisitObjCIvarRefExpr(ObjCIvarRefExpr *S) {
+void StmtProfiler::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *S) {
VisitExpr(S);
VisitDecl(S->getDecl());
ID.AddBoolean(S->isArrow());
ID.AddBoolean(S->isFreeIvar());
}
-void StmtProfiler::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *S) {
+void StmtProfiler::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *S) {
VisitExpr(S);
if (S->isImplicitProperty()) {
VisitDecl(S->getImplicitPropertyGetter());
@@ -941,22 +966,34 @@ void StmtProfiler::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *S) {
}
}
-void StmtProfiler::VisitObjCMessageExpr(ObjCMessageExpr *S) {
+void StmtProfiler::VisitObjCMessageExpr(const ObjCMessageExpr *S) {
VisitExpr(S);
VisitName(S->getSelector());
VisitDecl(S->getMethodDecl());
}
-void StmtProfiler::VisitObjCIsaExpr(ObjCIsaExpr *S) {
+void StmtProfiler::VisitObjCIsaExpr(const ObjCIsaExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isArrow());
}
-void StmtProfiler::VisitDecl(Decl *D) {
+void StmtProfiler::VisitObjCIndirectCopyRestoreExpr(
+ const ObjCIndirectCopyRestoreExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->shouldCopy());
+}
+
+void StmtProfiler::VisitObjCBridgedCastExpr(const ObjCBridgedCastExpr *S) {
+ VisitExplicitCastExpr(S);
+ ID.AddBoolean(S->getBridgeKind());
+}
+
+void StmtProfiler::VisitDecl(const Decl *D) {
ID.AddInteger(D? D->getKind() : 0);
if (Canonical && D) {
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ if (const NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(D)) {
ID.AddInteger(NTTP->getDepth());
ID.AddInteger(NTTP->getIndex());
ID.AddBoolean(NTTP->isParameterPack());
@@ -964,7 +1001,7 @@ void StmtProfiler::VisitDecl(Decl *D) {
return;
}
- if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
+ if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
// The Itanium C++ ABI uses the type, scope depth, and scope
// index of a parameter when mangling expressions that involve
// function parameters, so we will use the parameter's type for
@@ -978,7 +1015,8 @@ void StmtProfiler::VisitDecl(Decl *D) {
return;
}
- if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
+ if (const TemplateTemplateParmDecl *TTP =
+ dyn_cast<TemplateTemplateParmDecl>(D)) {
ID.AddInteger(TTP->getDepth());
ID.AddInteger(TTP->getIndex());
ID.AddBoolean(TTP->isParameterPack());
@@ -1058,7 +1096,7 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
}
void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
- bool Canonical) {
+ bool Canonical) const {
StmtProfiler Profiler(ID, Context, Canonical);
Profiler.Visit(this);
}
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 6114a5a051be..56c6e7bc47c1 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -104,6 +104,45 @@ bool TemplateArgument::isDependent() const {
return false;
}
+bool TemplateArgument::isInstantiationDependent() const {
+ switch (getKind()) {
+ case Null:
+ assert(false && "Should not have a NULL template argument");
+ return false;
+
+ case Type:
+ return getAsType()->isInstantiationDependentType();
+
+ case Template:
+ return getAsTemplate().isInstantiationDependent();
+
+ case TemplateExpansion:
+ return true;
+
+ case Declaration:
+ if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
+ return DC->isDependentContext();
+ return getAsDecl()->getDeclContext()->isDependentContext();
+
+ case Integral:
+ // Never dependent
+ return false;
+
+ case Expression:
+ return getAsExpr()->isInstantiationDependent();
+
+ case Pack:
+ for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
+ if (P->isInstantiationDependent())
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
bool TemplateArgument::isPackExpansion() const {
switch (getKind()) {
case Null:
@@ -277,8 +316,10 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
break;
case Type: {
+ PrintingPolicy SubPolicy(Policy);
+ SubPolicy.SuppressStrongLifetime = true;
std::string TypeStr;
- getAsType().getAsStringInternal(TypeStr, Policy);
+ getAsType().getAsStringInternal(TypeStr, SubPolicy);
Out << TypeStr;
break;
}
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
index ebd07f486783..1f7b19aae471 100644
--- a/lib/AST/TemplateName.cpp
+++ b/lib/AST/TemplateName.cpp
@@ -27,7 +27,19 @@ SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
return TemplateArgument(Arguments, size());
}
-void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID) {
+void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Parameter, Replacement);
+}
+
+void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
+ TemplateTemplateParmDecl *parameter,
+ TemplateName replacement) {
+ ID.AddPointer(parameter);
+ ID.AddPointer(replacement.getAsVoidPointer());
+}
+
+void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
+ ASTContext &Context) {
Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
}
@@ -46,9 +58,14 @@ TemplateName::NameKind TemplateName::getKind() const {
return DependentTemplate;
if (Storage.is<QualifiedTemplateName *>())
return QualifiedTemplate;
-
- return getAsOverloadedTemplate()? OverloadedTemplate
- : SubstTemplateTemplateParmPack;
+
+ UncommonTemplateNameStorage *uncommon
+ = Storage.get<UncommonTemplateNameStorage*>();
+ if (uncommon->getAsOverloadedStorage())
+ return OverloadedTemplate;
+ if (uncommon->getAsSubstTemplateTemplateParm())
+ return SubstTemplateTemplateParm;
+ return SubstTemplateTemplateParmPack;
}
TemplateDecl *TemplateName::getAsTemplateDecl() const {
@@ -58,6 +75,9 @@ TemplateDecl *TemplateName::getAsTemplateDecl() const {
if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
return QTN->getTemplateDecl();
+ if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
+ return sub->getReplacement().getAsTemplateDecl();
+
return 0;
}
@@ -79,6 +99,15 @@ bool TemplateName::isDependent() const {
return true;
}
+bool TemplateName::isInstantiationDependent() const {
+ if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
+ if (QTN->getQualifier()->isInstantiationDependent())
+ return true;
+ }
+
+ return isDependent();
+}
+
bool TemplateName::containsUnexpandedParameterPack() const {
if (TemplateDecl *Template = getAsTemplateDecl()) {
if (TemplateTemplateParmDecl *TTP
@@ -115,6 +144,9 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
OS << DTN->getIdentifier()->getName();
else
OS << "operator " << getOperatorSpelling(DTN->getOperator());
+ } else if (SubstTemplateTemplateParmStorage *subst
+ = getAsSubstTemplateTemplateParm()) {
+ subst->getReplacement().print(OS, Policy, SuppressNNS);
} else if (SubstTemplateTemplateParmPackStorage *SubstPack
= getAsSubstTemplateTemplateParmPack())
OS << SubstPack->getParameterPack()->getNameAsString();
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d28755284477..08971eb03421 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -36,7 +36,10 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const {
(hasObjCGCAttr() && !Other.hasObjCGCAttr())) &&
// Address space superset.
((getAddressSpace() == Other.getAddressSpace()) ||
- (hasAddressSpace()&& !Other.hasAddressSpace()));
+ (hasAddressSpace()&& !Other.hasAddressSpace())) &&
+ // Lifetime qualifier superset.
+ ((getObjCLifetime() == Other.getObjCLifetime()) ||
+ (hasObjCLifetime() && !Other.hasObjCLifetime()));
}
bool QualType::isConstant(QualType T, ASTContext &Ctx) {
@@ -107,6 +110,7 @@ DependentSizedExtVectorType::DependentSizedExtVectorType(const
Expr *SizeExpr,
SourceLocation loc)
: Type(DependentSizedExtVector, can, /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
ElementType->isVariablyModifiedType(),
(ElementType->containsUnexpandedParameterPack() ||
(SizeExpr && SizeExpr->containsUnexpandedParameterPack()))),
@@ -126,6 +130,7 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
VectorKind vecKind)
: Type(Vector, canonType, vecType->isDependentType(),
+ vecType->isInstantiationDependentType(),
vecType->isVariablyModifiedType(),
vecType->containsUnexpandedParameterPack()),
ElementType(vecType)
@@ -137,6 +142,7 @@ VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
QualType canonType, VectorKind vecKind)
: Type(tc, canonType, vecType->isDependentType(),
+ vecType->isInstantiationDependentType(),
vecType->isVariablyModifiedType(),
vecType->containsUnexpandedParameterPack()),
ElementType(vecType)
@@ -174,6 +180,26 @@ QualType QualType::getDesugaredType(QualType T, const ASTContext &Context) {
return Context.getQualifiedType(split.first, split.second);
}
+QualType QualType::getSingleStepDesugaredType(const ASTContext &Context) const {
+ QualifierCollector Qs;
+
+ const Type *CurTy = Qs.strip(*this);
+ switch (CurTy->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Type::Class: { \
+ const Class##Type *Ty = cast<Class##Type>(CurTy); \
+ if (!Ty->isSugared()) \
+ return *this; \
+ return Context.getQualifiedType(Ty->desugar(), Qs); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+
+ return *this;
+}
+
SplitQualType QualType::getSplitDesugaredType(QualType T) {
QualifierCollector Qs;
@@ -285,7 +311,6 @@ bool Type::isDerivedType() const {
return false;
}
}
-
bool Type::isClassType() const {
if (const RecordType *RT = getAs<RecordType>())
return RT->getDecl()->isClass();
@@ -385,7 +410,7 @@ const RecordType *Type::getAsUnionType() const {
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols)
- : Type(ObjCObject, Canonical, false, false, false),
+ : Type(ObjCObject, Canonical, false, false, false, false),
BaseType(Base)
{
ObjCObjectTypeBits.NumProtocols = NumProtocols;
@@ -866,39 +891,57 @@ bool Type::isIncompleteType() const {
}
}
-/// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10)
-bool Type::isPODType() const {
+bool QualType::isPODType(ASTContext &Context) const {
// The compiler shouldn't query this for incomplete types, but the user might.
// We return false for that case. Except for incomplete arrays of PODs, which
// are PODs according to the standard.
- if (isIncompleteArrayType() &&
- cast<ArrayType>(CanonicalType)->getElementType()->isPODType())
- return true;
- if (isIncompleteType())
+ if (isNull())
+ return 0;
+
+ if ((*this)->isIncompleteArrayType())
+ return Context.getBaseElementType(*this).isPODType(Context);
+
+ if ((*this)->isIncompleteType())
return false;
+ if (Context.getLangOptions().ObjCAutoRefCount) {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ break;
+ }
+ }
+
+ QualType CanonicalType = getTypePtr()->CanonicalType;
switch (CanonicalType->getTypeClass()) {
// Everything not explicitly mentioned is not POD.
default: return false;
- case VariableArray:
- case ConstantArray:
+ case Type::VariableArray:
+ case Type::ConstantArray:
// IncompleteArray is handled above.
- return cast<ArrayType>(CanonicalType)->getElementType()->isPODType();
-
- case Builtin:
- case Complex:
- case Pointer:
- case MemberPointer:
- case Vector:
- case ExtVector:
- case ObjCObjectPointer:
- case BlockPointer:
+ return Context.getBaseElementType(*this).isPODType(Context);
+
+ case Type::ObjCObjectPointer:
+ case Type::BlockPointer:
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Pointer:
+ case Type::MemberPointer:
+ case Type::Vector:
+ case Type::ExtVector:
return true;
- case Enum:
+ case Type::Enum:
return true;
- case Record:
+ case Type::Record:
if (CXXRecordDecl *ClassDecl
= dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
return ClassDecl->isPOD();
@@ -908,6 +951,121 @@ bool Type::isPODType() const {
}
}
+bool QualType::isTrivialType(ASTContext &Context) const {
+ // The compiler shouldn't query this for incomplete types, but the user might.
+ // We return false for that case. Except for incomplete arrays of PODs, which
+ // are PODs according to the standard.
+ if (isNull())
+ return 0;
+
+ if ((*this)->isArrayType())
+ return Context.getBaseElementType(*this).isTrivialType(Context);
+
+ // Return false for incomplete types after skipping any incomplete array
+ // types which are expressly allowed by the standard and thus our API.
+ if ((*this)->isIncompleteType())
+ return false;
+
+ if (Context.getLangOptions().ObjCAutoRefCount) {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ if ((*this)->isObjCLifetimeType())
+ return false;
+ break;
+ }
+ }
+
+ QualType CanonicalType = getTypePtr()->CanonicalType;
+ if (CanonicalType->isDependentType())
+ return false;
+
+ // C++0x [basic.types]p9:
+ // Scalar types, trivial class types, arrays of such types, and
+ // cv-qualified versions of these types are collectively called trivial
+ // types.
+
+ // As an extension, Clang treats vector types as Scalar types.
+ if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
+ return true;
+ if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
+ if (const CXXRecordDecl *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ // C++0x [class]p5:
+ // A trivial class is a class that has a trivial default constructor
+ if (!ClassDecl->hasTrivialDefaultConstructor()) return false;
+ // and is trivially copyable.
+ if (!ClassDecl->isTriviallyCopyable()) return false;
+ }
+
+ return true;
+ }
+
+ // No other types can match.
+ return false;
+}
+
+bool QualType::isTriviallyCopyableType(ASTContext &Context) const {
+ if ((*this)->isArrayType())
+ return Context.getBaseElementType(*this).isTrivialType(Context);
+
+ if (Context.getLangOptions().ObjCAutoRefCount) {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ if ((*this)->isObjCLifetimeType())
+ return false;
+ break;
+ }
+ }
+
+ // C++0x [basic.types]p9
+ // Scalar types, trivially copyable class types, arrays of such types, and
+ // cv-qualified versions of these types are collectively called trivial
+ // types.
+
+ QualType CanonicalType = getCanonicalType();
+ if (CanonicalType->isDependentType())
+ return false;
+
+ // Return false for incomplete types after skipping any incomplete array types
+ // which are expressly allowed by the standard and thus our API.
+ if (CanonicalType->isIncompleteType())
+ return false;
+
+ // As an extension, Clang treats vector types as Scalar types.
+ if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
+ return true;
+
+ if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
+ if (const CXXRecordDecl *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (!ClassDecl->isTriviallyCopyable()) return false;
+ }
+
+ return true;
+ }
+
+ // No other types can match.
+ return false;
+}
+
+
+
bool Type::isLiteralType() const {
if (isDependentType())
return false;
@@ -928,6 +1086,10 @@ bool Type::isLiteralType() const {
if (BaseTy->isIncompleteType())
return false;
+ // Objective-C lifetime types are not literal types.
+ if (BaseTy->isObjCRetainableType())
+ return false;
+
// C++0x [basic.types]p10:
// A type is a literal type if it is:
// -- a scalar type; or
@@ -961,68 +1123,6 @@ bool Type::isLiteralType() const {
return false;
}
-bool Type::isTrivialType() const {
- if (isDependentType())
- return false;
-
- // C++0x [basic.types]p9:
- // Scalar types, trivial class types, arrays of such types, and
- // cv-qualified versions of these types are collectively called trivial
- // types.
- const Type *BaseTy = getBaseElementTypeUnsafe();
- assert(BaseTy && "NULL element type");
-
- // Return false for incomplete types after skipping any incomplete array
- // types which are expressly allowed by the standard and thus our API.
- if (BaseTy->isIncompleteType())
- return false;
-
- // As an extension, Clang treats vector types as Scalar types.
- if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- if (!ClassDecl->isTrivial()) return false;
- }
-
- return true;
- }
-
- // No other types can match.
- return false;
-}
-
-bool Type::isTriviallyCopyableType() const {
- if (isDependentType())
- return false;
-
- // C++0x [basic.types]p9
- // Scalar types, trivially copyable class types, arrays of such types, and
- // cv-qualified versions of these types are collectively called trivial
- // types.
- const Type *BaseTy = getBaseElementTypeUnsafe();
- assert(BaseTy && "NULL element type");
-
- // Return false for incomplete types after skipping any incomplete array types
- // which are expressly allowed by the standard and thus our API.
- if (BaseTy->isIncompleteType())
- return false;
-
- // As an extension, Clang treats vector types as Scalar types.
- if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- if (!ClassDecl->isTriviallyCopyable()) return false;
- }
-
- return true;
- }
-
- // No other types can match.
- return false;
-}
-
bool Type::isStandardLayoutType() const {
if (isDependentType())
return false;
@@ -1060,14 +1160,32 @@ bool Type::isStandardLayoutType() const {
// This is effectively the intersection of isTrivialType and
// isStandardLayoutType. We implement it dircetly to avoid redundant
// conversions from a type to a CXXRecordDecl.
-bool Type::isCXX11PODType() const {
- if (isDependentType())
+bool QualType::isCXX11PODType(ASTContext &Context) const {
+ const Type *ty = getTypePtr();
+ if (ty->isDependentType())
return false;
+ if (Context.getLangOptions().ObjCAutoRefCount) {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ if (ty->isObjCLifetimeType())
+ return false;
+ break;
+ }
+ }
+
// C++11 [basic.types]p9:
// Scalar types, POD classes, arrays of such types, and cv-qualified
// versions of these types are collectively called trivial types.
- const Type *BaseTy = getBaseElementTypeUnsafe();
+ const Type *BaseTy = ty->getBaseElementTypeUnsafe();
assert(BaseTy && "NULL element type");
// Return false for incomplete types after skipping any incomplete array
@@ -1253,7 +1371,7 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType(
NestedNameSpecifier *NNS, const IdentifierInfo *Name,
unsigned NumArgs, const TemplateArgument *Args,
QualType Canon)
- : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true,
+ : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true,
/*VariablyModified=*/false,
NNS && NNS->containsUnexpandedParameterPack()),
NNS(NNS), Name(Name), NumArgs(NumArgs) {
@@ -1388,18 +1506,22 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
: FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals,
epi.RefQualifier, canonical,
result->isDependentType(),
+ result->isInstantiationDependentType(),
result->isVariablyModifiedType(),
result->containsUnexpandedParameterPack(),
epi.ExtInfo),
NumArgs(numArgs), NumExceptions(epi.NumExceptions),
- ExceptionSpecType(epi.ExceptionSpecType)
+ ExceptionSpecType(epi.ExceptionSpecType),
+ HasAnyConsumedArgs(epi.ConsumedArguments != 0)
{
// Fill in the trailing argument array.
QualType *argSlot = reinterpret_cast<QualType*>(this+1);
for (unsigned i = 0; i != numArgs; ++i) {
if (args[i]->isDependentType())
setDependent();
-
+ else if (args[i]->isInstantiationDependentType())
+ setInstantiationDependent();
+
if (args[i]->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
@@ -1412,7 +1534,9 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) {
if (epi.Exceptions[i]->isDependentType())
setDependent();
-
+ else if (epi.Exceptions[i]->isInstantiationDependentType())
+ setInstantiationDependent();
+
if (epi.Exceptions[i]->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
@@ -1422,6 +1546,20 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
// Store the noexcept expression and context.
Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + numArgs);
*noexSlot = epi.NoexceptExpr;
+
+ if (epi.NoexceptExpr) {
+ if (epi.NoexceptExpr->isValueDependent()
+ || epi.NoexceptExpr->isTypeDependent())
+ setDependent();
+ else if (epi.NoexceptExpr->isInstantiationDependent())
+ setInstantiationDependent();
+ }
+ }
+
+ if (epi.ConsumedArguments) {
+ bool *consumedArgs = const_cast<bool*>(getConsumedArgsBuffer());
+ for (unsigned i = 0; i != numArgs; ++i)
+ consumedArgs[i] = epi.ConsumedArguments[i];
}
}
@@ -1461,18 +1599,48 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
const QualType *ArgTys, unsigned NumArgs,
const ExtProtoInfo &epi,
const ASTContext &Context) {
+
+ // We have to be careful not to get ambiguous profile encodings.
+ // Note that valid type pointers are never ambiguous with anything else.
+ //
+ // The encoding grammar begins:
+ // type type* bool int bool
+ // If that final bool is true, then there is a section for the EH spec:
+ // bool type*
+ // This is followed by an optional "consumed argument" section of the
+ // same length as the first type sequence:
+ // bool*
+ // Finally, we have the ext info:
+ // int
+ //
+ // There is no ambiguity between the consumed arguments and an empty EH
+ // spec because of the leading 'bool' which unambiguously indicates
+ // whether the following bool is the EH spec or part of the arguments.
+
ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
- ID.AddBoolean(epi.Variadic);
- ID.AddInteger(epi.TypeQuals);
- ID.AddInteger(epi.RefQualifier);
- ID.AddInteger(epi.ExceptionSpecType);
+ // This method is relatively performance sensitive, so as a performance
+ // shortcut, use one AddInteger call instead of four for the next four
+ // fields.
+ assert(!(unsigned(epi.Variadic) & ~1) &&
+ !(unsigned(epi.TypeQuals) & ~255) &&
+ !(unsigned(epi.RefQualifier) & ~3) &&
+ !(unsigned(epi.ExceptionSpecType) & ~7) &&
+ "Values larger than expected.");
+ ID.AddInteger(unsigned(epi.Variadic) +
+ (epi.TypeQuals << 1) +
+ (epi.RefQualifier << 9) +
+ (epi.ExceptionSpecType << 11));
if (epi.ExceptionSpecType == EST_Dynamic) {
for (unsigned i = 0; i != epi.NumExceptions; ++i)
ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
} else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){
- epi.NoexceptExpr->Profile(ID, Context, true);
+ epi.NoexceptExpr->Profile(ID, Context, false);
+ }
+ if (epi.ConsumedArguments) {
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ID.AddBoolean(epi.ConsumedArguments[i]);
}
epi.ExtInfo.Profile(ID);
}
@@ -1489,13 +1657,21 @@ QualType TypedefType::desugar() const {
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
: Type(TypeOfExpr, can, E->isTypeDependent(),
+ E->isInstantiationDependent(),
E->getType()->isVariablyModifiedType(),
E->containsUnexpandedParameterPack()),
TOExpr(E) {
}
+bool TypeOfExprType::isSugared() const {
+ return !TOExpr->isTypeDependent();
+}
+
QualType TypeOfExprType::desugar() const {
- return getUnderlyingExpr()->getType();
+ if (isSugared())
+ return getUnderlyingExpr()->getType();
+
+ return QualType(this, 0);
}
void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
@@ -1505,12 +1681,22 @@ void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
: Type(Decltype, can, E->isTypeDependent(),
+ E->isInstantiationDependent(),
E->getType()->isVariablyModifiedType(),
E->containsUnexpandedParameterPack()),
E(E),
UnderlyingType(underlyingType) {
}
+bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
+
+QualType DecltypeType::desugar() const {
+ if (isSugared())
+ return getUnderlyingType();
+
+ return QualType(this, 0);
+}
+
DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E)
: DecltypeType(E, Context.DependentTy), Context(Context) { }
@@ -1520,7 +1706,9 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
}
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
- : Type(TC, can, D->isDependentType(), /*VariablyModified=*/false,
+ : Type(TC, can, D->isDependentType(),
+ /*InstantiationDependent=*/D->isDependentType(),
+ /*VariablyModified=*/false,
/*ContainsUnexpandedParameterPack=*/false),
decl(const_cast<TagDecl*>(D)) {}
@@ -1540,6 +1728,7 @@ UnaryTransformType::UnaryTransformType(QualType BaseType,
UTTKind UKind,
QualType CanonicalType)
: Type(UnaryTransform, CanonicalType, UnderlyingType->isDependentType(),
+ UnderlyingType->isInstantiationDependentType(),
UnderlyingType->isVariablyModifiedType(),
BaseType->containsUnexpandedParameterPack())
, BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind)
@@ -1573,7 +1762,8 @@ SubstTemplateTypeParmPackType::
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
QualType Canon,
const TemplateArgument &ArgPack)
- : Type(SubstTemplateTypeParmPack, Canon, true, false, true), Replaced(Param),
+ : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true),
+ Replaced(Param),
Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size())
{
}
@@ -1598,23 +1788,39 @@ void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
}
bool TemplateSpecializationType::
-anyDependentTemplateArguments(const TemplateArgumentListInfo &Args) {
- return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size());
+anyDependentTemplateArguments(const TemplateArgumentListInfo &Args,
+ bool &InstantiationDependent) {
+ return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size(),
+ InstantiationDependent);
}
bool TemplateSpecializationType::
-anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) {
- for (unsigned i = 0; i != N; ++i)
- if (Args[i].getArgument().isDependent())
+anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N,
+ bool &InstantiationDependent) {
+ for (unsigned i = 0; i != N; ++i) {
+ if (Args[i].getArgument().isDependent()) {
+ InstantiationDependent = true;
return true;
+ }
+
+ if (Args[i].getArgument().isInstantiationDependent())
+ InstantiationDependent = true;
+ }
return false;
}
bool TemplateSpecializationType::
-anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) {
- for (unsigned i = 0; i != N; ++i)
- if (Args[i].isDependent())
+anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N,
+ bool &InstantiationDependent) {
+ for (unsigned i = 0; i != N; ++i) {
+ if (Args[i].isDependent()) {
+ InstantiationDependent = true;
return true;
+ }
+
+ if (Args[i].isInstantiationDependent())
+ InstantiationDependent = true;
+ }
return false;
}
@@ -1625,12 +1831,22 @@ TemplateSpecializationType(TemplateName T,
: Type(TemplateSpecialization,
Canon.isNull()? QualType(this, 0) : Canon,
Canon.isNull()? T.isDependent() : Canon->isDependentType(),
+ Canon.isNull()? T.isDependent()
+ : Canon->isInstantiationDependentType(),
false, T.containsUnexpandedParameterPack()),
Template(T), NumArgs(NumArgs) {
assert(!T.getAsDependentTemplateName() &&
"Use DependentTemplateSpecializationType for dependent template-name");
+ assert((T.getKind() == TemplateName::Template ||
+ T.getKind() == TemplateName::SubstTemplateTemplateParm ||
+ T.getKind() == TemplateName::SubstTemplateTemplateParmPack) &&
+ "Unexpected template name for TemplateSpecializationType");
+ bool InstantiationDependent;
+ (void)InstantiationDependent;
assert((!Canon.isNull() ||
- T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) &&
+ T.isDependent() ||
+ anyDependentTemplateArguments(Args, NumArgs,
+ InstantiationDependent)) &&
"No canonical type for non-dependent class template specialization");
TemplateArgument *TemplateArgs
@@ -1644,6 +1860,9 @@ TemplateSpecializationType(TemplateName T,
// U<T> is always non-dependent, irrespective of the type T.
if (Canon.isNull() && Args[Arg].isDependent())
setDependent();
+ else if (Args[Arg].isInstantiationDependent())
+ setInstantiationDependent();
+
if (Args[Arg].getKind() == TemplateArgument::Type &&
Args[Arg].getAsType()->isVariablyModifiedType())
setVariablyModified();
@@ -1795,8 +2014,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
#define DEPENDENT_TYPE(Class,Base) case Type::Class:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
- // Treat dependent types as external.
- assert(T->isDependentType());
+ // Treat instantiation-dependent types as external.
+ assert(T->isInstantiationDependentType());
return CachedProperties(ExternalLinkage, DefaultVisibility, false);
case Type::Builtin:
@@ -1900,6 +2119,79 @@ void Type::ClearLinkageCache() {
CanonicalType->TypeBits.CacheValidAndVisibility = 0;
}
+Qualifiers::ObjCLifetime Type::getObjCARCImplicitLifetime() const {
+ if (isObjCARCImplicitlyUnretainedType())
+ return Qualifiers::OCL_ExplicitNone;
+ return Qualifiers::OCL_Strong;
+}
+
+bool Type::isObjCARCImplicitlyUnretainedType() const {
+ assert(isObjCLifetimeType() &&
+ "cannot query implicit lifetime for non-inferrable type");
+
+ const Type *canon = getCanonicalTypeInternal().getTypePtr();
+
+ // Walk down to the base type. We don't care about qualifiers for this.
+ while (const ArrayType *array = dyn_cast<ArrayType>(canon))
+ canon = array->getElementType().getTypePtr();
+
+ if (const ObjCObjectPointerType *opt
+ = dyn_cast<ObjCObjectPointerType>(canon)) {
+ // Class and Class<Protocol> don't require retension.
+ if (opt->getObjectType()->isObjCClass())
+ return true;
+ }
+
+ return false;
+}
+
+bool Type::isObjCNSObjectType() const {
+ if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+ return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
+ return false;
+}
+bool Type::isObjCRetainableType() const {
+ return isObjCObjectPointerType() ||
+ isBlockPointerType() ||
+ isObjCNSObjectType();
+}
+bool Type::isObjCIndirectLifetimeType() const {
+ if (isObjCLifetimeType())
+ return true;
+ if (const PointerType *OPT = getAs<PointerType>())
+ return OPT->getPointeeType()->isObjCIndirectLifetimeType();
+ if (const ReferenceType *Ref = getAs<ReferenceType>())
+ return Ref->getPointeeType()->isObjCIndirectLifetimeType();
+ if (const MemberPointerType *MemPtr = getAs<MemberPointerType>())
+ return MemPtr->getPointeeType()->isObjCIndirectLifetimeType();
+ return false;
+}
+
+/// Returns true if objects of this type have lifetime semantics under
+/// ARC.
+bool Type::isObjCLifetimeType() const {
+ const Type *type = this;
+ while (const ArrayType *array = type->getAsArrayTypeUnsafe())
+ type = array->getElementType().getTypePtr();
+ return type->isObjCRetainableType();
+}
+
+/// \brief Determine whether the given type T is a "bridgable" Objective-C type,
+/// which is either an Objective-C object pointer type or an
+bool Type::isObjCARCBridgableType() const {
+ return isObjCObjectPointerType() || isBlockPointerType();
+}
+
+/// \brief Determine whether the given type T is a "bridgeable" C type.
+bool Type::isCARCBridgableType() const {
+ const PointerType *Pointer = getAs<PointerType>();
+ if (!Pointer)
+ return false;
+
+ QualType Pointee = Pointer->getPointeeType();
+ return Pointee->isVoidType() || Pointee->isRecordType();
+}
+
bool Type::hasSizedVLAType() const {
if (!isVariablyModifiedType()) return false;
@@ -1919,6 +2211,18 @@ bool Type::hasSizedVLAType() const {
}
QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
+ switch (type.getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ break;
+
+ case Qualifiers::OCL_Strong:
+ return DK_objc_strong_lifetime;
+ case Qualifiers::OCL_Weak:
+ return DK_objc_weak_lifetime;
+ }
+
/// Currently, the only destruction kind we recognize is C++ objects
/// with non-trivial destructors.
const CXXRecordDecl *record =
@@ -1928,3 +2232,24 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
return DK_none;
}
+
+bool QualType::hasTrivialCopyAssignment(ASTContext &Context) const {
+ switch (getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ break;
+
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Autoreleasing:
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ return !Context.getLangOptions().ObjCAutoRefCount;
+ }
+
+ if (const CXXRecordDecl *Record
+ = getTypePtr()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
+ return Record->hasTrivialCopyAssignment();
+
+ return true;
+}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 4519606f6e82..b89d2aa31676 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -24,6 +24,23 @@
using namespace clang;
namespace {
+ /// \brief RAII object that enables printing of the ARC __strong lifetime
+ /// qualifier.
+ class IncludeStrongLifetimeRAII {
+ PrintingPolicy &Policy;
+ bool Old;
+
+ public:
+ explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
+ : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
+ Policy.SuppressStrongLifetime = false;
+ }
+
+ ~IncludeStrongLifetimeRAII() {
+ Policy.SuppressStrongLifetime = Old;
+ }
+ };
+
class TypePrinter {
PrintingPolicy Policy;
@@ -78,7 +95,7 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
// "int * const", printing "const int *" is different. Only do this when the
// type expands to a simple string.
bool CanPrefixQualifiers = false;
-
+ bool NeedARCStrongQualifier = false;
Type::TypeClass TC = T->getTypeClass();
if (const AutoType *AT = dyn_cast<AutoType>(T))
TC = AT->desugar()->getTypeClass();
@@ -114,15 +131,18 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
break;
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ NeedARCStrongQualifier = true;
+ // Fall through
+
case Type::Pointer:
case Type::BlockPointer:
case Type::LValueReference:
case Type::RValueReference:
case Type::MemberPointer:
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- case Type::DependentSizedArray:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@@ -139,13 +159,20 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
if (!CanPrefixQualifiers && !Quals.empty()) {
std::string qualsBuffer;
- Quals.getAsStringInternal(qualsBuffer, Policy);
+ if (NeedARCStrongQualifier) {
+ IncludeStrongLifetimeRAII Strong(Policy);
+ Quals.getAsStringInternal(qualsBuffer, Policy);
+ } else {
+ Quals.getAsStringInternal(qualsBuffer, Policy);
+ }
- if (!buffer.empty()) {
- qualsBuffer += ' ';
- qualsBuffer += buffer;
+ if (!qualsBuffer.empty()) {
+ if (!buffer.empty()) {
+ qualsBuffer += ' ';
+ qualsBuffer += buffer;
+ }
+ std::swap(buffer, qualsBuffer);
}
- std::swap(buffer, qualsBuffer);
}
switch (T->getTypeClass()) {
@@ -159,13 +186,20 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
// If we're adding the qualifiers as a prefix, do it now.
if (CanPrefixQualifiers && !Quals.empty()) {
std::string qualsBuffer;
- Quals.getAsStringInternal(qualsBuffer, Policy);
-
- if (!buffer.empty()) {
- qualsBuffer += ' ';
- qualsBuffer += buffer;
+ if (NeedARCStrongQualifier) {
+ IncludeStrongLifetimeRAII Strong(Policy);
+ Quals.getAsStringInternal(qualsBuffer, Policy);
+ } else {
+ Quals.getAsStringInternal(qualsBuffer, Policy);
+ }
+
+ if (!qualsBuffer.empty()) {
+ if (!buffer.empty()) {
+ qualsBuffer += ' ';
+ qualsBuffer += buffer;
+ }
+ std::swap(buffer, qualsBuffer);
}
- std::swap(buffer, qualsBuffer);
}
}
@@ -192,6 +226,7 @@ void TypePrinter::printPointer(const PointerType *T, std::string &S) {
if (isa<ArrayType>(T->getPointeeType()))
S = '(' + S + ')';
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getPointeeType(), S);
}
@@ -209,6 +244,7 @@ void TypePrinter::printLValueReference(const LValueReferenceType *T,
if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
S = '(' + S + ')';
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getPointeeTypeAsWritten(), S);
}
@@ -221,6 +257,7 @@ void TypePrinter::printRValueReference(const RValueReferenceType *T,
if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
S = '(' + S + ')';
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getPointeeTypeAsWritten(), S);
}
@@ -236,6 +273,7 @@ void TypePrinter::printMemberPointer(const MemberPointerType *T,
if (isa<ArrayType>(T->getPointeeType()))
S = '(' + S + ')';
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getPointeeType(), S);
}
@@ -245,12 +283,14 @@ void TypePrinter::printConstantArray(const ConstantArrayType *T,
S += llvm::utostr(T->getSize().getZExtValue());
S += ']';
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getElementType(), S);
}
void TypePrinter::printIncompleteArray(const IncompleteArrayType *T,
std::string &S) {
S += "[]";
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getElementType(), S);
}
@@ -276,6 +316,7 @@ void TypePrinter::printVariableArray(const VariableArrayType *T,
}
S += ']';
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getElementType(), S);
}
@@ -291,6 +332,7 @@ void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T,
}
S += ']';
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getElementType(), S);
}
@@ -518,6 +560,7 @@ void TypePrinter::printUnaryTransform(const UnaryTransformType *T,
if (!S.empty())
S = ' ' + S;
std::string Str;
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getBaseType(), Str);
switch (T->getUTTKind()) {
@@ -552,6 +595,7 @@ void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
Buffer += "<anonymous>";
} else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
+ IncludeStrongLifetimeRAII Strong(Policy);
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
std::string TemplateArgsStr
= TemplateSpecializationType::PrintTemplateArgumentList(
@@ -642,6 +686,7 @@ void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
Args = TemplateArgs.data();
NumArgs = TemplateArgs.size();
}
+ IncludeStrongLifetimeRAII Strong(Policy);
Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
NumArgs,
Policy);
@@ -677,18 +722,21 @@ void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
std::string &S) {
+ IncludeStrongLifetimeRAII Strong(Policy);
print(T->getReplacementType(), S);
}
void TypePrinter::printSubstTemplateTypeParmPack(
const SubstTemplateTypeParmPackType *T,
std::string &S) {
+ IncludeStrongLifetimeRAII Strong(Policy);
printTemplateTypeParm(T->getReplacedParameter(), S);
}
void TypePrinter::printTemplateSpecialization(
const TemplateSpecializationType *T,
std::string &S) {
+ IncludeStrongLifetimeRAII Strong(Policy);
std::string SpecString;
{
@@ -765,6 +813,7 @@ void TypePrinter::printDependentName(const DependentNameType *T, std::string &S)
void TypePrinter::printDependentTemplateSpecialization(
const DependentTemplateSpecializationType *T, std::string &S) {
+ IncludeStrongLifetimeRAII Strong(Policy);
std::string MyString;
{
llvm::raw_string_ostream OS(MyString);
@@ -796,8 +845,9 @@ void TypePrinter::printPackExpansion(const PackExpansionType *T,
void TypePrinter::printAttributed(const AttributedType *T,
std::string &S) {
- // Prefer the macro forms of the GC qualifiers.
- if (T->getAttrKind() == AttributedType::attr_objc_gc)
+ // Prefer the macro forms of the GC and ownership qualifiers.
+ if (T->getAttrKind() == AttributedType::attr_objc_gc ||
+ T->getAttrKind() == AttributedType::attr_objc_ownership)
return print(T->getEquivalentType(), S);
print(T->getModifiedType(), S);
@@ -866,6 +916,18 @@ void TypePrinter::printAttributed(const AttributedType *T,
break;
}
+ case AttributedType::attr_objc_ownership:
+ S += "objc_ownership(";
+ switch (T->getEquivalentType().getObjCLifetime()) {
+ case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); break;
+ case Qualifiers::OCL_ExplicitNone: S += "none"; break;
+ case Qualifiers::OCL_Strong: S += "strong"; break;
+ case Qualifiers::OCL_Weak: S += "weak"; break;
+ case Qualifiers::OCL_Autoreleasing: S += "autoreleasing"; break;
+ }
+ S += ")";
+ break;
+
case AttributedType::attr_noreturn: S += "noreturn"; break;
case AttributedType::attr_cdecl: S += "cdecl"; break;
case AttributedType::attr_fastcall: S += "fastcall"; break;
@@ -1080,7 +1142,7 @@ std::string Qualifiers::getAsString() const {
// prefix a space if the string is non-empty. Will not append a final
// space.
void Qualifiers::getAsStringInternal(std::string &S,
- const PrintingPolicy&) const {
+ const PrintingPolicy& Policy) const {
AppendTypeQualList(S, getCVRQualifiers());
if (unsigned addrspace = getAddressSpace()) {
if (!S.empty()) S += ' ';
@@ -1095,6 +1157,23 @@ void Qualifiers::getAsStringInternal(std::string &S,
else
S += "__strong";
}
+ if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
+ if (!S.empty() &&
+ !(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
+ S += ' ';
+
+ switch (lifetime) {
+ case Qualifiers::OCL_None: llvm_unreachable("none but true");
+ case Qualifiers::OCL_ExplicitNone: S += "__unsafe_unretained"; break;
+ case Qualifiers::OCL_Strong:
+ if (!Policy.SuppressStrongLifetime)
+ S += "__strong";
+ break;
+
+ case Qualifiers::OCL_Weak: S += "__weak"; break;
+ case Qualifiers::OCL_Autoreleasing: S += "__autoreleasing"; break;
+ }
+ }
}
std::string QualType::getAsString(const Type *ty, Qualifiers qs) {