diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 293 | ||||
-rw-r--r-- | lib/AST/ASTDiagnostic.cpp | 74 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 20 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 110 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 35 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 54 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 58 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/AST/DeclarationName.cpp | 22 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 256 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 60 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 15 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 68 | ||||
-rw-r--r-- | lib/AST/ExternalASTSource.cpp | 4 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 447 | ||||
-rw-r--r-- | lib/AST/NestedNameSpecifier.cpp | 22 | ||||
-rw-r--r-- | lib/AST/ParentMap.cpp | 9 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 9 | ||||
-rw-r--r-- | lib/AST/Stmt.cpp | 33 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 26 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 308 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 43 | ||||
-rw-r--r-- | lib/AST/TemplateName.cpp | 40 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 547 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 117 |
25 files changed, 2000 insertions, 675 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 9094aba..6eada6e 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 16d2f85..7c91b5c 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 100e604..f5e392f 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 12357c0..4c323da 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 1766d39..b2806f0 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 08ac2a5..4b59bf3 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 e2c4f38..557b681 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 421770e..19554a3 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 cef54e9..72c0e9d 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 9872139..4611ae3 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 1a1a0a3..f92afff 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 d177cb5..e7888a6 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 06c5645..786155a 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 f428318..b96d65a 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 e81ec7e..ec9863b 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 2878dff..f6d4f25 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 eca351a..b7b2005 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 de0b1d0..5636a6f 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 380ad94..fd6f21d 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 87588e4..f705a84 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 b117cd9..120c9e5 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 6114a5a..56c6e7b 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 ebd07f4..1f7b19a 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 d2875528..08971eb 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 4519606..b89d2aa 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) { |