diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
25 files changed, 2614 insertions, 1328 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 851f8d1..d41051f 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -31,25 +31,128 @@ using namespace clang; +unsigned ASTContext::NumImplicitDefaultConstructors; +unsigned ASTContext::NumImplicitDefaultConstructorsDeclared; +unsigned ASTContext::NumImplicitCopyConstructors; +unsigned ASTContext::NumImplicitCopyConstructorsDeclared; +unsigned ASTContext::NumImplicitCopyAssignmentOperators; +unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; +unsigned ASTContext::NumImplicitDestructors; +unsigned ASTContext::NumImplicitDestructorsDeclared; + enum FloatingRank { FloatRank, DoubleRank, LongDoubleRank }; +void +ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, + TemplateTemplateParmDecl *Parm) { + ID.AddInteger(Parm->getDepth()); + ID.AddInteger(Parm->getPosition()); + // FIXME: Parameter pack + + TemplateParameterList *Params = Parm->getTemplateParameters(); + ID.AddInteger(Params->size()); + for (TemplateParameterList::const_iterator P = Params->begin(), + PEnd = Params->end(); + P != PEnd; ++P) { + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { + ID.AddInteger(0); + ID.AddBoolean(TTP->isParameterPack()); + continue; + } + + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + ID.AddInteger(1); + // FIXME: Parameter pack + ID.AddPointer(NTTP->getType().getAsOpaquePtr()); + continue; + } + + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); + ID.AddInteger(2); + Profile(ID, TTP); + } +} + +TemplateTemplateParmDecl * +ASTContext::getCanonicalTemplateTemplateParmDecl( + TemplateTemplateParmDecl *TTP) { + // Check if we already have a canonical template template parameter. + llvm::FoldingSetNodeID ID; + CanonicalTemplateTemplateParm::Profile(ID, TTP); + void *InsertPos = 0; + CanonicalTemplateTemplateParm *Canonical + = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); + if (Canonical) + return Canonical->getParam(); + + // Build a canonical template parameter list. + TemplateParameterList *Params = TTP->getTemplateParameters(); + llvm::SmallVector<NamedDecl *, 4> CanonParams; + CanonParams.reserve(Params->size()); + for (TemplateParameterList::const_iterator P = Params->begin(), + PEnd = Params->end(); + P != PEnd; ++P) { + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) + CanonParams.push_back( + TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(), + SourceLocation(), TTP->getDepth(), + TTP->getIndex(), 0, false, + TTP->isParameterPack())); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(*P)) + CanonParams.push_back( + NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(), + SourceLocation(), NTTP->getDepth(), + NTTP->getPosition(), 0, + getCanonicalType(NTTP->getType()), + 0)); + else + CanonParams.push_back(getCanonicalTemplateTemplateParmDecl( + cast<TemplateTemplateParmDecl>(*P))); + } + + TemplateTemplateParmDecl *CanonTTP + = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(), + SourceLocation(), TTP->getDepth(), + TTP->getPosition(), 0, + TemplateParameterList::Create(*this, SourceLocation(), + SourceLocation(), + CanonParams.data(), + CanonParams.size(), + SourceLocation())); + + // Get the new insert position for the node we care about. + Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); + assert(Canonical == 0 && "Shouldn't be in the map!"); + (void)Canonical; + + // Create the canonical template template parameter entry. + Canonical = new (*this) CanonicalTemplateTemplateParm(CanonTTP); + CanonTemplateTemplateParms.InsertNode(Canonical, InsertPos); + return CanonTTP; +} + ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, bool FreeMem, unsigned size_reserve) : - GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), - NSConstantStringTypeDecl(0), + TemplateSpecializationTypes(this_()), + DependentTemplateSpecializationTypes(this_()), + GlobalNestedNameSpecifier(0), IsInt128Installed(false), + CFConstantStringTypeDecl(0), NSConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), + NullTypeSourceInfo(QualType()), SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(0), PrintingPolicy(LOpts), - LastSDM(0, 0) { + LastSDM(0, 0), + UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) { ObjCIdRedefinitionType = QualType(); ObjCClassRedefinitionType = QualType(); ObjCSelRedefinitionType = QualType(); @@ -88,13 +191,6 @@ ASTContext::~ASTContext() { Deallocate(&*I++); } - for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator - I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) { - // Increment in loop to prevent using deallocated memory. - if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second)) - R->Destroy(*this); - } - for (llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*>::iterator I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; ) { @@ -104,6 +200,16 @@ ASTContext::~ASTContext() { } } + // ASTRecordLayout objects in ASTRecordLayouts must always be destroyed + // even when using the BumpPtrAllocator because they can contain + // DenseMaps. + for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator + I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) { + // Increment in loop to prevent using deallocated memory. + if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second)) + R->Destroy(*this); + } + // Destroy nested-name-specifiers. for (llvm::FoldingSet<NestedNameSpecifier>::iterator NNS = NestedNameSpecifiers.begin(), @@ -155,11 +261,30 @@ void ASTContext::PrintStats() const { #include "clang/AST/TypeNodes.def" fprintf(stderr, "Total bytes = %d\n", int(TotalBytes)); - + + // 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); + fprintf(stderr, " %u/%u implicit copy assignment operators created\n", + NumImplicitCopyAssignmentOperatorsDeclared, + NumImplicitCopyAssignmentOperators); + fprintf(stderr, " %u/%u implicit destructors created\n", + NumImplicitDestructorsDeclared, NumImplicitDestructors); + + if (!FreeMemory) + BumpAlloc.PrintStats(); + if (ExternalSource.get()) { fprintf(stderr, "\n"); ExternalSource->PrintStats(); } + + if (!FreeMemory) + BumpAlloc.PrintStats(); } @@ -273,13 +398,14 @@ ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) { void ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, - TemplateSpecializationKind TSK) { + TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation) { assert(Inst->isStaticDataMember() && "Not a static data member"); assert(Tmpl->isStaticDataMember() && "Not a static data member"); assert(!InstantiatedFromStaticDataMember[Inst] && "Already noted what static data member was instantiated from"); InstantiatedFromStaticDataMember[Inst] - = new (*this) MemberSpecializationInfo(Tmpl, TSK); + = new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation); } NamedDecl * @@ -358,6 +484,16 @@ ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const { return Pos->second.end(); } +unsigned +ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const { + llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos + = OverriddenMethods.find(Method); + if (Pos == OverriddenMethods.end()) + return 0; + + return Pos->second.size(); +} + void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method, const CXXMethodDecl *Overridden) { OverriddenMethods[Method].push_back(Overridden); @@ -414,6 +550,15 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) { T = getPointerType(RT->getPointeeType()); } if (!T->isIncompleteType() && !T->isFunctionType()) { + unsigned MinWidth = Target.getLargeArrayMinWidth(); + unsigned ArrayAlign = Target.getLargeArrayAlign(); + if (isa<VariableArrayType>(T) && MinWidth != 0) + Align = std::max(Align, ArrayAlign); + if (ConstantArrayType *CT = dyn_cast<ConstantArrayType>(T)) { + unsigned Size = getTypeSize(CT); + if (MinWidth != 0 && MinWidth <= Size) + Align = std::max(Align, ArrayAlign); + } // Incomplete or function types default to 1. while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T)) T = cast<ArrayType>(T)->getElementType(); @@ -762,7 +907,8 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { // Find ivars declared in class extension. - if (const ObjCCategoryDecl *CDecl = OI->getClassExtension()) { + for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; + CDecl = CDecl->getNextClassExtension()) { for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), E = CDecl->ivar_end(); I != E; ++I) { Ivars.push_back(*I); @@ -827,7 +973,8 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) { unsigned count = 0; // Count ivars declared in class extension. - if (const ObjCCategoryDecl *CDecl = OI->getClassExtension()) + for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; + CDecl = CDecl->getNextClassExtension()) count += CDecl->ivar_size(); // Count ivar defined in this class's implementation. This @@ -1406,7 +1553,7 @@ QualType ASTContext::getIncompleteArrayType(QualType EltTy, /// getVectorType - Return the unique reference to a vector type of /// the specified element type and size. VectorType must be a built-in type. QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, - bool IsAltiVec, bool IsPixel) { + VectorType::AltiVecSpecific AltiVecSpec) { BuiltinType *baseType; baseType = dyn_cast<BuiltinType>(getCanonicalType(vecType).getTypePtr()); @@ -1414,8 +1561,8 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, // Check if we've already instantiated a vector of this type. llvm::FoldingSetNodeID ID; - VectorType::Profile(ID, vecType, NumElts, Type::Vector, - IsAltiVec, IsPixel); + VectorType::Profile(ID, vecType, NumElts, Type::Vector, AltiVecSpec); + void *InsertPos = 0; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(VTP, 0); @@ -1423,16 +1570,19 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, // If the element type isn't canonical, this won't be a canonical type either, // so fill in the canonical type field. QualType Canonical; - if (!vecType.isCanonical() || IsAltiVec || IsPixel) { - Canonical = getVectorType(getCanonicalType(vecType), - NumElts, false, false); + if (!vecType.isCanonical() || (AltiVecSpec == VectorType::AltiVec)) { + // pass VectorType::NotAltiVec for AltiVecSpec to make AltiVec canonical + // vector type (except 'vector bool ...' and 'vector Pixel') the same as + // the equivalent GCC vector types + Canonical = getVectorType(getCanonicalType(vecType), NumElts, + VectorType::NotAltiVec); // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; } VectorType *New = new (*this, TypeAlignment) - VectorType(vecType, NumElts, Canonical, IsAltiVec, IsPixel); + VectorType(vecType, NumElts, Canonical, AltiVecSpec); VectorTypes.InsertNode(New, InsertPos); Types.push_back(New); return QualType(New, 0); @@ -1448,7 +1598,8 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) { // Check if we've already instantiated a vector of this type. llvm::FoldingSetNodeID ID; - VectorType::Profile(ID, vecType, NumElts, Type::ExtVector, false, false); + VectorType::Profile(ID, vecType, NumElts, Type::ExtVector, + VectorType::NotAltiVec); void *InsertPos = 0; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(VTP, 0); @@ -1629,8 +1780,7 @@ QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl, assert(NeedsInjectedClassNameType(Decl)); if (Decl->TypeForDecl) { assert(isa<InjectedClassNameType>(Decl->TypeForDecl)); - } else if (CXXRecordDecl *PrevDecl - = cast_or_null<CXXRecordDecl>(Decl->getPreviousDeclaration())) { + } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDeclaration()) { assert(PrevDecl->TypeForDecl && "previous declaration has no type"); Decl->TypeForDecl = PrevDecl->TypeForDecl; assert(isa<InjectedClassNameType>(Decl->TypeForDecl)); @@ -1658,11 +1808,11 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) { assert(!Record->getPreviousDeclaration() && "struct/union has previous declaration"); assert(!NeedsInjectedClassNameType(Record)); - Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Record); + return getRecordType(Record); } else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) { assert(!Enum->getPreviousDeclaration() && "enum has previous declaration"); - Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum); + return getEnumType(Enum); } else if (const UnresolvedUsingTypenameDecl *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) { Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using); @@ -1675,16 +1825,42 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) { /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. -QualType ASTContext::getTypedefType(const TypedefDecl *Decl) { +QualType +ASTContext::getTypedefType(const TypedefDecl *Decl, QualType Canonical) { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); - QualType Canonical = getCanonicalType(Decl->getUnderlyingType()); + if (Canonical.isNull()) + Canonical = getCanonicalType(Decl->getUnderlyingType()); Decl->TypeForDecl = new(*this, TypeAlignment) TypedefType(Type::Typedef, Decl, Canonical); Types.push_back(Decl->TypeForDecl); return QualType(Decl->TypeForDecl, 0); } +QualType ASTContext::getRecordType(const RecordDecl *Decl) { + if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + + if (const RecordDecl *PrevDecl = Decl->getPreviousDeclaration()) + if (PrevDecl->TypeForDecl) + return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); + + Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Decl); + Types.push_back(Decl->TypeForDecl); + return QualType(Decl->TypeForDecl, 0); +} + +QualType ASTContext::getEnumType(const EnumDecl *Decl) { + if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + + if (const EnumDecl *PrevDecl = Decl->getPreviousDeclaration()) + if (PrevDecl->TypeForDecl) + return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); + + Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Decl); + Types.push_back(Decl->TypeForDecl); + return QualType(Decl->TypeForDecl, 0); +} + /// \brief Retrieve a substitution-result type. QualType ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, @@ -1763,8 +1939,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgumentListInfo &Args, - QualType Canon, - bool IsCurrentInstantiation) { + QualType Canon) { unsigned NumArgs = Args.size(); llvm::SmallVector<TemplateArgument, 4> ArgVec; @@ -1773,56 +1948,18 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, ArgVec.push_back(Args[i].getArgument()); return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs, - Canon, IsCurrentInstantiation); + Canon); } QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, unsigned NumArgs, - QualType Canon, - bool IsCurrentInstantiation) { + QualType Canon) { if (!Canon.isNull()) Canon = getCanonicalType(Canon); - else { - assert(!IsCurrentInstantiation && - "current-instantiation specializations should always " - "have a canonical type"); - - // Build the canonical template specialization type. - TemplateName CanonTemplate = getCanonicalTemplateName(Template); - llvm::SmallVector<TemplateArgument, 4> CanonArgs; - CanonArgs.reserve(NumArgs); - for (unsigned I = 0; I != NumArgs; ++I) - CanonArgs.push_back(getCanonicalTemplateArgument(Args[I])); - - // Determine whether this canonical template specialization type already - // exists. - llvm::FoldingSetNodeID ID; - TemplateSpecializationType::Profile(ID, CanonTemplate, false, - CanonArgs.data(), NumArgs, *this); - - void *InsertPos = 0; - TemplateSpecializationType *Spec - = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); - - if (!Spec) { - // Allocate a new canonical template specialization type. - void *Mem = Allocate((sizeof(TemplateSpecializationType) + - sizeof(TemplateArgument) * NumArgs), - TypeAlignment); - Spec = new (Mem) TemplateSpecializationType(*this, CanonTemplate, false, - CanonArgs.data(), NumArgs, - Canon); - Types.push_back(Spec); - TemplateSpecializationTypes.InsertNode(Spec, InsertPos); - } - - if (Canon.isNull()) - Canon = QualType(Spec, 0); - assert(Canon->isDependentType() && - "Non-dependent template-id type must have a canonical type"); - } + else + Canon = getCanonicalTemplateSpecializationType(Template, Args, NumArgs); // Allocate the (non-canonical) template specialization type, but don't // try to unique it: these types typically have location information that @@ -1831,8 +1968,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, sizeof(TemplateArgument) * NumArgs), TypeAlignment); TemplateSpecializationType *Spec - = new (Mem) TemplateSpecializationType(*this, Template, - IsCurrentInstantiation, + = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, Canon); @@ -1841,6 +1977,44 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, } QualType +ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, + const TemplateArgument *Args, + unsigned NumArgs) { + // Build the canonical template specialization type. + TemplateName CanonTemplate = getCanonicalTemplateName(Template); + llvm::SmallVector<TemplateArgument, 4> CanonArgs; + CanonArgs.reserve(NumArgs); + for (unsigned I = 0; I != NumArgs; ++I) + CanonArgs.push_back(getCanonicalTemplateArgument(Args[I])); + + // Determine whether this canonical template specialization type already + // exists. + llvm::FoldingSetNodeID ID; + TemplateSpecializationType::Profile(ID, CanonTemplate, + CanonArgs.data(), NumArgs, *this); + + void *InsertPos = 0; + TemplateSpecializationType *Spec + = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); + + if (!Spec) { + // Allocate a new canonical template specialization type. + void *Mem = Allocate((sizeof(TemplateSpecializationType) + + sizeof(TemplateArgument) * NumArgs), + TypeAlignment); + Spec = new (Mem) TemplateSpecializationType(CanonTemplate, + CanonArgs.data(), NumArgs, + QualType()); + Types.push_back(Spec); + TemplateSpecializationTypes.InsertNode(Spec, InsertPos); + } + + assert(Spec->isDependentType() && + "Non-dependent template-id type must have a canonical type"); + return QualType(Spec, 0); +} + +QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType) { @@ -1898,44 +2072,69 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, } QualType -ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, +ASTContext::getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const TemplateSpecializationType *TemplateId, - QualType Canon) { + const IdentifierInfo *Name, + const TemplateArgumentListInfo &Args) { + // TODO: avoid this copy + llvm::SmallVector<TemplateArgument, 16> ArgCopy; + for (unsigned I = 0, E = Args.size(); I != E; ++I) + ArgCopy.push_back(Args[I].getArgument()); + return getDependentTemplateSpecializationType(Keyword, NNS, Name, + ArgCopy.size(), + ArgCopy.data()); +} + +QualType +ASTContext::getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args) { assert(NNS->isDependent() && "nested-name-specifier must be dependent"); llvm::FoldingSetNodeID ID; - DependentNameType::Profile(ID, Keyword, NNS, TemplateId); + DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS, + Name, NumArgs, Args); void *InsertPos = 0; - DependentNameType *T - = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); + DependentTemplateSpecializationType *T + = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); - if (Canon.isNull()) { - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - QualType CanonType = getCanonicalType(QualType(TemplateId, 0)); - ElaboratedTypeKeyword CanonKeyword = Keyword; - if (Keyword == ETK_None) - CanonKeyword = ETK_Typename; - if (CanonNNS != NNS || CanonKeyword != Keyword || - CanonType != QualType(TemplateId, 0)) { - const TemplateSpecializationType *CanonTemplateId - = CanonType->getAs<TemplateSpecializationType>(); - assert(CanonTemplateId && - "Canonical type must also be a template specialization type"); - Canon = getDependentNameType(CanonKeyword, CanonNNS, CanonTemplateId); - } + NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + + ElaboratedTypeKeyword CanonKeyword = Keyword; + if (Keyword == ETK_None) CanonKeyword = ETK_Typename; - DependentNameType *CheckT - = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!CheckT && "Typename canonical type is broken"); (void)CheckT; + bool AnyNonCanonArgs = false; + llvm::SmallVector<TemplateArgument, 16> CanonArgs(NumArgs); + for (unsigned I = 0; I != NumArgs; ++I) { + CanonArgs[I] = getCanonicalTemplateArgument(Args[I]); + if (!CanonArgs[I].structurallyEquals(Args[I])) + AnyNonCanonArgs = true; } - T = new (*this) DependentNameType(Keyword, NNS, TemplateId, Canon); + QualType Canon; + if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) { + Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS, + Name, NumArgs, + CanonArgs.data()); + + // Find the insert position again. + DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); + } + + void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) + + sizeof(TemplateArgument) * NumArgs), + TypeAlignment); + T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS, + Name, NumArgs, Args, Canon); Types.push_back(T); - DependentNameTypes.InsertNode(T, InsertPos); + DependentTemplateSpecializationTypes.InsertNode(T, InsertPos); return QualType(T, 0); } @@ -2326,6 +2525,48 @@ QualType ASTContext::getUnqualifiedArrayType(QualType T, SourceRange()); } +/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that +/// may be similar (C++ 4.4), replaces T1 and T2 with the type that +/// they point to and return true. If T1 and T2 aren't pointer types +/// or pointer-to-member types, or if they are not similar at this +/// level, returns false and leaves T1 and T2 unchanged. Top-level +/// qualifiers on T1 and T2 are ignored. This function will typically +/// be called in a loop that successively "unwraps" pointer and +/// pointer-to-member types to compare them at each level. +bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) { + const PointerType *T1PtrType = T1->getAs<PointerType>(), + *T2PtrType = T2->getAs<PointerType>(); + if (T1PtrType && T2PtrType) { + T1 = T1PtrType->getPointeeType(); + T2 = T2PtrType->getPointeeType(); + return true; + } + + const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(), + *T2MPType = T2->getAs<MemberPointerType>(); + if (T1MPType && T2MPType && + hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0), + QualType(T2MPType->getClass(), 0))) { + T1 = T1MPType->getPointeeType(); + T2 = T2MPType->getPointeeType(); + return true; + } + + if (getLangOptions().ObjC1) { + const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(), + *T2OPType = T2->getAs<ObjCObjectPointerType>(); + if (T1OPType && T2OPType) { + T1 = T1OPType->getPointeeType(); + T2 = T2OPType->getPointeeType(); + return true; + } + } + + // FIXME: Block pointers, too? + + return false; +} + DeclarationName ASTContext::getNameForTemplate(TemplateName Name) { if (TemplateDecl *TD = Name.getAsTemplateDecl()) return TD->getDeclName(); @@ -2344,10 +2585,14 @@ DeclarationName ASTContext::getNameForTemplate(TemplateName Name) { } TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { - // If this template name refers to a template, the canonical - // template name merely stores the template itself. - if (TemplateDecl *Template = Name.getAsTemplateDecl()) + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + if (TemplateTemplateParmDecl *TTP + = dyn_cast<TemplateTemplateParmDecl>(Template)) + Template = getCanonicalTemplateTemplateParmDecl(TTP); + + // The canonical template name is the canonical template declaration. return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl())); + } assert(!Name.getAsOverloadedTemplate()); @@ -2856,6 +3101,10 @@ QualType ASTContext::getObjCFastEnumerationStateType() { Field->setAccess(AS_public); ObjCFastEnumerationStateTypeDecl->addDecl(Field); } + if (getLangOptions().CPlusPlus) + if (CXXRecordDecl *CXXRD = + dyn_cast<CXXRecordDecl>(ObjCFastEnumerationStateTypeDecl)) + CXXRD->setEmpty(false); ObjCFastEnumerationStateTypeDecl->completeDefinition(); } @@ -2981,7 +3230,6 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) { bool HasCopyAndDispose = BlockRequiresCopying(Ty); // FIXME: Move up - static unsigned int UniqueBlockByRefTypeID = 0; llvm::SmallString<36> Name; llvm::raw_svector_ostream(Name) << "__Block_byref_" << ++UniqueBlockByRefTypeID << '_' << DeclName; @@ -3033,7 +3281,6 @@ QualType ASTContext::getBlockParmType( llvm::SmallVectorImpl<const Expr *> &Layout) { // FIXME: Move up - static unsigned int UniqueBlockParmTypeID = 0; llvm::SmallString<36> Name; llvm::raw_svector_ostream(Name) << "__block_literal_" << ++UniqueBlockParmTypeID; @@ -3122,7 +3369,7 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) { CharUnits sz = getTypeSizeInChars(type); // Make all integer and enum types at least as large as an int - if (sz.isPositive() && type->isIntegralType()) + if (sz.isPositive() && type->isIntegralOrEnumerationType()) sz = std::max(sz, getTypeSizeInChars(IntTy)); // Treat arrays as pointers, since that's how they're passed in. else if (type->isArrayType()) @@ -3143,7 +3390,7 @@ void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr, QualType BlockTy = Expr->getType()->getAs<BlockPointerType>()->getPointeeType(); // Encode result type. - getObjCEncodingForType(cast<FunctionType>(BlockTy)->getResultType(), S); + getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), S); // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! @@ -3376,13 +3623,74 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S, true /* outermost type */); } +static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { + switch (T->getAs<BuiltinType>()->getKind()) { + default: assert(0 && "Unhandled builtin type kind"); + case BuiltinType::Void: return 'v'; + case BuiltinType::Bool: return 'B'; + case BuiltinType::Char_U: + case BuiltinType::UChar: return 'C'; + case BuiltinType::UShort: return 'S'; + case BuiltinType::UInt: return 'I'; + case BuiltinType::ULong: + return + (const_cast<ASTContext *>(C))->getIntWidth(T) == 32 ? 'L' : 'Q'; + case BuiltinType::UInt128: return 'T'; + case BuiltinType::ULongLong: return 'Q'; + case BuiltinType::Char_S: + case BuiltinType::SChar: return 'c'; + case BuiltinType::Short: return 's'; + case BuiltinType::WChar: + case BuiltinType::Int: return 'i'; + case BuiltinType::Long: + return + (const_cast<ASTContext *>(C))->getIntWidth(T) == 32 ? 'l' : 'q'; + case BuiltinType::LongLong: return 'q'; + case BuiltinType::Int128: return 't'; + case BuiltinType::Float: return 'f'; + case BuiltinType::Double: return 'd'; + case BuiltinType::LongDouble: return 'd'; + } +} + static void EncodeBitField(const ASTContext *Context, std::string& S, - const FieldDecl *FD) { + QualType T, const FieldDecl *FD) { const Expr *E = FD->getBitWidth(); assert(E && "bitfield width not there - getObjCEncodingForTypeImpl"); ASTContext *Ctx = const_cast<ASTContext*>(Context); - unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue(); S += 'b'; + // The NeXT runtime encodes bit fields as b followed by the number of bits. + // The GNU runtime requires more information; bitfields are encoded as b, + // then the offset (in bits) of the first element, then the type of the + // bitfield, then the size in bits. For example, in this structure: + // + // struct + // { + // int integer; + // int flags:2; + // }; + // On a 32-bit system, the encoding for flags would be b2 for the NeXT + // runtime, but b32i2 for the GNU runtime. The reason for this extra + // information is not especially sensible, but we're stuck with it for + // compatibility with GCC, although providing it breaks anything that + // actually uses runtime introspection and wants to work on both runtimes... + 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 += ObjCEncodingForPrimitiveKind(Context, T); + } + unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue(); S += llvm::utostr(N); } @@ -3393,40 +3701,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, const FieldDecl *FD, bool OutermostType, bool EncodingProperty) { - if (const BuiltinType *BT = T->getAs<BuiltinType>()) { + if (T->getAs<BuiltinType>()) { if (FD && FD->isBitField()) - return EncodeBitField(this, S, FD); - char encoding; - switch (BT->getKind()) { - default: assert(0 && "Unhandled builtin type kind"); - case BuiltinType::Void: encoding = 'v'; break; - case BuiltinType::Bool: encoding = 'B'; break; - case BuiltinType::Char_U: - case BuiltinType::UChar: encoding = 'C'; break; - case BuiltinType::UShort: encoding = 'S'; break; - case BuiltinType::UInt: encoding = 'I'; break; - case BuiltinType::ULong: - encoding = - (const_cast<ASTContext *>(this))->getIntWidth(T) == 32 ? 'L' : 'Q'; - break; - case BuiltinType::UInt128: encoding = 'T'; break; - case BuiltinType::ULongLong: encoding = 'Q'; break; - case BuiltinType::Char_S: - case BuiltinType::SChar: encoding = 'c'; break; - case BuiltinType::Short: encoding = 's'; break; - case BuiltinType::Int: encoding = 'i'; break; - case BuiltinType::Long: - encoding = - (const_cast<ASTContext *>(this))->getIntWidth(T) == 32 ? 'l' : 'q'; - break; - case BuiltinType::LongLong: encoding = 'q'; break; - case BuiltinType::Int128: encoding = 't'; break; - case BuiltinType::Float: encoding = 'f'; break; - case BuiltinType::Double: encoding = 'd'; break; - case BuiltinType::LongDouble: encoding = 'd'; break; - } - - S += encoding; + return EncodeBitField(this, S, T, FD); + S += ObjCEncodingForPrimitiveKind(this, T); return; } @@ -3585,7 +3863,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (T->isEnumeralType()) { if (FD && FD->isBitField()) - EncodeBitField(this, S, FD); + EncodeBitField(this, S, T, FD); else S += 'i'; return; @@ -4728,7 +5006,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) { // Turn <4 x signed int> -> <4 x unsigned int> if (const VectorType *VTy = T->getAs<VectorType>()) return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()), - VTy->getNumElements(), VTy->isAltiVec(), VTy->isPixel()); + VTy->getNumElements(), VTy->getAltiVecSpecific()); // For enums, we return the unsigned version of the base type. if (const EnumType *ETy = T->getAs<EnumType>()) @@ -4886,7 +5164,8 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false); // FIXME: Don't know what to do about AltiVec. - Type = Context.getVectorType(ElementType, NumElements, false, false); + Type = Context.getVectorType(ElementType, NumElements, + VectorType::NotAltiVec); break; } case 'X': { diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index 6ed08d1..8d347d1 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -73,6 +73,7 @@ namespace { // FIXME: TemplateSpecializationType QualType VisitElaboratedType(ElaboratedType *T); // FIXME: DependentNameType + // FIXME: DependentTemplateSpecializationType QualType VisitObjCInterfaceType(ObjCInterfaceType *T); QualType VisitObjCObjectType(ObjCObjectType *T); QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T); @@ -439,9 +440,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; if (Vec1->getNumElements() != Vec2->getNumElements()) return false; - if (Vec1->isAltiVec() != Vec2->isAltiVec()) - return false; - if (Vec1->isPixel() != Vec2->isPixel()) + if (Vec1->getAltiVecSpecific() != Vec2->getAltiVecSpecific()) return false; break; } @@ -619,14 +618,32 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Typename1->getIdentifier(), Typename2->getIdentifier())) return false; - if (!IsStructurallyEquivalent(Context, - QualType(Typename1->getTemplateId(), 0), - QualType(Typename2->getTemplateId(), 0))) - return false; break; } + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *Spec1 = + cast<DependentTemplateSpecializationType>(T1); + const DependentTemplateSpecializationType *Spec2 = + cast<DependentTemplateSpecializationType>(T2); + if (!IsStructurallyEquivalent(Context, + Spec1->getQualifier(), + Spec2->getQualifier())) + return false; + if (!IsStructurallyEquivalent(Spec1->getIdentifier(), + Spec2->getIdentifier())) + return false; + if (Spec1->getNumArgs() != Spec2->getNumArgs()) + return false; + for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, + Spec1->getArg(I), Spec2->getArg(I))) + return false; + } + break; + } + case Type::ObjCInterface: { const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1); const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2); @@ -1172,8 +1189,7 @@ QualType ASTNodeImporter::VisitVectorType(VectorType *T) { return Importer.getToContext().getVectorType(ToElementType, T->getNumElements(), - T->isAltiVec(), - T->isPixel()); + T->getAltiVecSpecific()); } QualType ASTNodeImporter::VisitExtVectorType(ExtVectorType *T) { @@ -1687,7 +1703,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // Create the record declaration. RecordDecl *D2 = AdoptDecl; if (!D2) { - if (CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(D)) { + if (isa<CXXRecordDecl>(D)) { CXXRecordDecl *D2CXX = CXXRecordDecl::Create(Importer.getToContext(), D->getTagKind(), DC, Loc, @@ -1695,30 +1711,6 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Importer.Import(D->getTagKeywordLoc())); D2 = D2CXX; D2->setAccess(D->getAccess()); - - if (D->isDefinition()) { - // Add base classes. - llvm::SmallVector<CXXBaseSpecifier *, 4> Bases; - for (CXXRecordDecl::base_class_iterator - Base1 = D1CXX->bases_begin(), - FromBaseEnd = D1CXX->bases_end(); - Base1 != FromBaseEnd; - ++Base1) { - QualType T = Importer.Import(Base1->getType()); - if (T.isNull()) - return 0; - - Bases.push_back( - new (Importer.getToContext()) - CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()), - Base1->isVirtual(), - Base1->isBaseOfClass(), - Base1->getAccessSpecifierAsWritten(), - T)); - } - if (!Bases.empty()) - D2CXX->setBases(Bases.data(), Bases.size()); - } } else { D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), DC, Loc, @@ -1739,6 +1731,33 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (D->isDefinition()) { D2->startDefinition(); + + // Add base classes. + if (CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(D2)) { + CXXRecordDecl *D1CXX = cast<CXXRecordDecl>(D); + + llvm::SmallVector<CXXBaseSpecifier *, 4> Bases; + for (CXXRecordDecl::base_class_iterator + Base1 = D1CXX->bases_begin(), + FromBaseEnd = D1CXX->bases_end(); + Base1 != FromBaseEnd; + ++Base1) { + QualType T = Importer.Import(Base1->getType()); + if (T.isNull()) + return 0; + + Bases.push_back( + new (Importer.getToContext()) + CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()), + Base1->isVirtual(), + Base1->isBaseOfClass(), + Base1->getAccessSpecifierAsWritten(), + T)); + } + if (!Bases.empty()) + D2CXX->setBases(Bases.data(), Bases.size()); + } + ImportDeclContext(D); D2->completeDefinition(); } @@ -2598,8 +2617,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { } // Import the type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) + TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo()); + if (!T) return 0; // Create the new property. @@ -2614,6 +2633,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { LexicalDC->addDecl(ToProperty); ToProperty->setPropertyAttributes(D->getPropertyAttributes()); + ToProperty->setPropertyAttributesAsWritten( + D->getPropertyAttributesAsWritten()); ToProperty->setGetterName(Importer.Import(D->getGetterName())); ToProperty->setSetterName(Importer.Import(D->getSetterName())); ToProperty->setGetterMethodDecl( diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp index 0fab22c..b09ba895 100644 --- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp @@ -24,7 +24,7 @@ void Attr::Destroy(ASTContext &C) { C.Deallocate((void*)this); } -AttrWithString::AttrWithString(Attr::Kind AK, ASTContext &C, llvm::StringRef s) +AttrWithString::AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s) : Attr(AK) { assert(!s.empty()); StrLen = s.size(); @@ -51,7 +51,7 @@ void FormatAttr::setType(ASTContext &C, llvm::StringRef type) { } NonNullAttr::NonNullAttr(ASTContext &C, unsigned* arg_nums, unsigned size) - : Attr(NonNull), ArgNums(0), Size(0) { + : Attr(attr::NonNull), ArgNums(0), Size(0) { if (size == 0) return; assert(arg_nums); @@ -93,6 +93,7 @@ DEF_SIMPLE_ATTR_CLONE(NSReturnsNotRetained) DEF_SIMPLE_ATTR_CLONE(NSReturnsRetained) DEF_SIMPLE_ATTR_CLONE(NoDebug) DEF_SIMPLE_ATTR_CLONE(NoInline) +DEF_SIMPLE_ATTR_CLONE(NoInstrumentFunction) DEF_SIMPLE_ATTR_CLONE(NoReturn) DEF_SIMPLE_ATTR_CLONE(NoThrow) DEF_SIMPLE_ATTR_CLONE(ObjCException) @@ -200,6 +201,10 @@ Attr *ReqdWorkGroupSizeAttr::clone(ASTContext &C) const { return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z); } +Attr *InitPriorityAttr::clone(ASTContext &C) const { + return ::new (C) InitPriorityAttr(Priority); +} + Attr *MSP430InterruptAttr::clone(ASTContext &C) const { return ::new (C) MSP430InterruptAttr(Number); } diff --git a/contrib/llvm/tools/clang/lib/AST/CMakeLists.txt b/contrib/llvm/tools/clang/lib/AST/CMakeLists.txt index bce3646..407ed95 100644 --- a/contrib/llvm/tools/clang/lib/AST/CMakeLists.txt +++ b/contrib/llvm/tools/clang/lib/AST/CMakeLists.txt @@ -18,6 +18,7 @@ add_clang_library(clangAST DeclPrinter.cpp DeclTemplate.cpp Expr.cpp + ExprClassification.cpp ExprConstant.cpp ExprCXX.cpp FullExpr.cpp @@ -39,4 +40,5 @@ add_clang_library(clangAST TypePrinter.cpp ) -add_dependencies(clangAST ClangDiagnosticAST ClangStmtNodes) +add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList + ClangDiagnosticAST ClangDeclNodes ClangStmtNodes) diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index d616e42..c563c37 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -90,6 +90,9 @@ bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) cons } bool CXXRecordDecl::isVirtuallyDerivedFrom(CXXRecordDecl *Base) const { + if (!getNumVBases()) + return false; + CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, /*DetectVirtual=*/false); @@ -559,22 +562,23 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, for (; OverMethods.first != OverMethods.second; ++OverMethods.first) { const CXXMethodDecl *CanonOM = cast<CXXMethodDecl>((*OverMethods.first)->getCanonicalDecl()); + + // C++ [class.virtual]p2: + // A virtual member function C::vf of a class object S is + // a final overrider unless the most derived class (1.8) + // of which S is a base class subobject (if any) declares + // or inherits another member function that overrides vf. + // + // Treating this object like the most derived class, we + // replace any overrides from base classes with this + // overriding virtual function. + Overriders[CanonOM].replaceAll( + UniqueVirtualMethod(CanonM, SubobjectNumber, + InVirtualSubobject)); + if (CanonOM->begin_overridden_methods() - == CanonOM->end_overridden_methods()) { - // C++ [class.virtual]p2: - // A virtual member function C::vf of a class object S is - // a final overrider unless the most derived class (1.8) - // of which S is a base class subobject (if any) declares - // or inherits another member function that overrides vf. - // - // Treating this object like the most derived class, we - // replace any overrides from base classes with this - // overriding virtual function. - Overriders[CanonOM].replaceAll( - UniqueVirtualMethod(CanonM, SubobjectNumber, - InVirtualSubobject)); + == CanonOM->end_overridden_methods()) continue; - } // Continue recursion to the methods that this virtual method // overrides. @@ -582,6 +586,12 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, CanonOM->end_overridden_methods())); } } + + // C++ [class.virtual]p2: + // For convenience we say that any virtual function overrides itself. + Overriders[CanonM].add(SubobjectNumber, + UniqueVirtualMethod(CanonM, SubobjectNumber, + InVirtualSubobject)); } } diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index ffdcb47..149938f 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -523,6 +523,14 @@ bool NamedDecl::isCXXInstanceMember() const { // DeclaratorDecl Implementation //===----------------------------------------------------------------------===// +template <typename DeclT> +static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) { + if (decl->getNumTemplateParameterLists() > 0) + return decl->getTemplateParameterList(0)->getTemplateLoc(); + else + return decl->getInnerLocStart(); +} + DeclaratorDecl::~DeclaratorDecl() {} void DeclaratorDecl::Destroy(ASTContext &C) { if (hasExtInfo()) @@ -531,15 +539,8 @@ void DeclaratorDecl::Destroy(ASTContext &C) { } SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { - if (DeclInfo) { - TypeLoc TL = getTypeSourceInfo()->getTypeLoc(); - while (true) { - TypeLoc NextTL = TL.getNextTypeLoc(); - if (!NextTL) - return TL.getLocalSourceRange().getBegin(); - TL = NextTL; - } - } + TypeSourceInfo *TSI = getTypeSourceInfo(); + if (TSI) return TSI->getTypeLoc().getBeginLoc(); return SourceLocation(); } @@ -573,6 +574,40 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, } } +SourceLocation DeclaratorDecl::getOuterLocStart() const { + return getTemplateOrInnerLocStart(this); +} + +void +QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, + unsigned NumTPLists, + TemplateParameterList **TPLists) { + assert((NumTPLists == 0 || TPLists != 0) && + "Empty array of template parameters with positive size!"); + assert((NumTPLists == 0 || NNS) && + "Nonempty array of template parameters with no qualifier!"); + + // Free previous template parameters (if any). + if (NumTemplParamLists > 0) { + Context.Deallocate(TemplParamLists); + TemplParamLists = 0; + NumTemplParamLists = 0; + } + // Set info on matched template parameter lists (if any). + if (NumTPLists > 0) { + TemplParamLists = new (Context) TemplateParameterList*[NumTPLists]; + NumTemplParamLists = NumTPLists; + for (unsigned i = NumTPLists; i-- > 0; ) + TemplParamLists[i] = TPLists[i]; + } +} + +void QualifierInfo::Destroy(ASTContext &Context) { + // FIXME: Deallocate template parameter lists themselves! + if (TemplParamLists) + Context.Deallocate(TemplParamLists); +} + //===----------------------------------------------------------------------===// // VarDecl Implementation //===----------------------------------------------------------------------===// @@ -613,14 +648,17 @@ void VarDecl::Destroy(ASTContext& C) { VarDecl::~VarDecl() { } -SourceRange VarDecl::getSourceRange() const { +SourceLocation VarDecl::getInnerLocStart() const { SourceLocation Start = getTypeSpecStartLoc(); if (Start.isInvalid()) Start = getLocation(); - + return Start; +} + +SourceRange VarDecl::getSourceRange() const { if (getInit()) - return SourceRange(Start, getInit()->getLocEnd()); - return SourceRange(Start, getLocation()); + return SourceRange(getOuterLocStart(), getInit()->getLocEnd()); + return SourceRange(getOuterLocStart(), getLocation()); } bool VarDecl::isExternC() const { @@ -678,7 +716,15 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const { // AST for 'extern "C" int foo;' is annotated with 'extern'. if (hasExternalStorage()) return DeclarationOnly; - + + if (getStorageClassAsWritten() == Extern || + getStorageClassAsWritten() == PrivateExtern) { + for (const VarDecl *PrevVar = getPreviousDeclaration(); + PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) { + if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit()) + return DeclarationOnly; + } + } // C99 6.9.2p2: // A declaration of an object that has file scope without an initializer, // and without a storage class specifier or the scs 'static', constitutes @@ -697,7 +743,7 @@ VarDecl *VarDecl::getActingDefinition() { if (Kind != TentativeDefinition) return 0; - VarDecl *LastTentative = false; + VarDecl *LastTentative = 0; VarDecl *First = getFirstDeclaration(); for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); I != E; ++I) { @@ -907,6 +953,17 @@ bool FunctionDecl::isVariadic() const { return false; } +bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + if (I->Body) { + Definition = *I; + return true; + } + } + + return false; +} + Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { if (I->Body) { @@ -1107,11 +1164,11 @@ bool FunctionDecl::isInlined() const { } const FunctionDecl *PatternDecl = getTemplateInstantiationPattern(); - Stmt *Pattern = 0; + bool HasPattern = false; if (PatternDecl) - Pattern = PatternDecl->getBody(PatternDecl); + HasPattern = PatternDecl->hasBody(PatternDecl); - if (Pattern && PatternDecl) + if (HasPattern && PatternDecl) return PatternDecl->isInlined(); return false; @@ -1197,6 +1254,23 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const { return 0; } +FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { + if (TemplateOrSpecialization.isNull()) + return TK_NonTemplate; + if (TemplateOrSpecialization.is<FunctionTemplateDecl *>()) + return TK_FunctionTemplate; + if (TemplateOrSpecialization.is<MemberSpecializationInfo *>()) + return TK_MemberSpecialization; + if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>()) + return TK_FunctionTemplateSpecialization; + if (TemplateOrSpecialization.is + <DependentFunctionTemplateSpecializationInfo*>()) + return TK_DependentFunctionTemplateSpecialization; + + assert(false && "Did we miss a TemplateOrSpecialization type?"); + return TK_NonTemplate; +} + FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) return cast<FunctionDecl>(Info->getInstantiatedFrom()); @@ -1239,15 +1313,15 @@ bool FunctionDecl::isImplicitlyInstantiable() const { // Find the actual template from which we will instantiate. const FunctionDecl *PatternDecl = getTemplateInstantiationPattern(); - Stmt *Pattern = 0; + bool HasPattern = false; if (PatternDecl) - Pattern = PatternDecl->getBody(PatternDecl); + HasPattern = PatternDecl->hasBody(PatternDecl); // C++0x [temp.explicit]p9: // Except for inline functions, other explicit instantiation declarations // have the effect of suppressing the implicit instantiation of the entity // to which they refer. - if (!Pattern || !PatternDecl) + if (!HasPattern || !PatternDecl) return true; return PatternDecl->isInlined(); @@ -1304,7 +1378,8 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, TemplateSpecializationKind TSK, - const TemplateArgumentListInfo *TemplateArgsAsWritten) { + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation) { assert(TSK != TSK_Undeclared && "Must specify the type of function template specialization"); FunctionTemplateSpecializationInfo *Info @@ -1317,6 +1392,7 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, Info->Template.setInt(TSK - 1); Info->TemplateArguments = TemplateArgs; Info->TemplateArgumentsAsWritten = TemplateArgsAsWritten; + Info->PointOfInstantiation = PointOfInstantiation; TemplateOrSpecialization = Info; // Insert this function template specialization into the set of known @@ -1336,6 +1412,28 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, } void +FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, + unsigned NumTemplateArgs, + const TemplateArgument *TemplateArgs, + TemplateSpecializationKind TSK, + unsigned NumTemplateArgsAsWritten, + TemplateArgumentLoc *TemplateArgsAsWritten, + SourceLocation LAngleLoc, + SourceLocation RAngleLoc, + SourceLocation PointOfInstantiation) { + ASTContext &Ctx = getASTContext(); + TemplateArgumentList *TemplArgs + = new (Ctx) TemplateArgumentList(Ctx, TemplateArgs, NumTemplateArgs); + TemplateArgumentListInfo *TemplArgsInfo + = new (Ctx) TemplateArgumentListInfo(LAngleLoc, RAngleLoc); + for (unsigned i=0; i != NumTemplateArgsAsWritten; ++i) + TemplArgsInfo->addArgument(TemplateArgsAsWritten[i]); + + setFunctionTemplateSpecialization(Template, TemplArgs, /*InsertPos=*/0, TSK, + TemplArgsInfo, PointOfInstantiation); +} + +void FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context, const UnresolvedSetImpl &Templates, const TemplateArgumentListInfo &TemplateArgs) { @@ -1427,7 +1525,7 @@ bool FunctionDecl::isOutOfLine() const { // class template, check whether that member function was defined out-of-line. if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) { const FunctionDecl *Definition; - if (FD->getBody(Definition)) + if (FD->hasBody(Definition)) return Definition->isOutOfLine(); } @@ -1435,7 +1533,7 @@ bool FunctionDecl::isOutOfLine() const { // check whether that function template was defined out-of-line. if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) { const FunctionDecl *Definition; - if (FunTmpl->getTemplatedDecl()->getBody(Definition)) + if (FunTmpl->getTemplatedDecl()->hasBody(Definition)) return Definition->isOutOfLine(); } @@ -1472,9 +1570,13 @@ void TagDecl::Destroy(ASTContext &C) { TypeDecl::Destroy(C); } +SourceLocation TagDecl::getOuterLocStart() const { + return getTemplateOrInnerLocStart(this); +} + SourceRange TagDecl::getSourceRange() const { SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation(); - return SourceRange(TagKeywordLoc, E); + return SourceRange(getOuterLocStart(), E); } TagDecl* TagDecl::getCanonicalDecl() { @@ -1569,6 +1671,10 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, return Enum; } +EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation()); +} + void EnumDecl::Destroy(ASTContext& C) { TagDecl::Destroy(C); } @@ -1608,6 +1714,11 @@ RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, return R; } +RecordDecl *RecordDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), 0, 0, + SourceLocation()); +} + RecordDecl::~RecordDecl() { } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 42a3726..d4f997d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -35,16 +35,18 @@ using namespace clang; // Statistics //===----------------------------------------------------------------------===// -#define DECL(Derived, Base) static int n##Derived##s = 0; -#include "clang/AST/DeclNodes.def" +#define DECL(DERIVED, BASE) static int n##DERIVED##s = 0; +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" static bool StatSwitch = false; const char *Decl::getDeclKindName() const { switch (DeclKind) { - default: assert(0 && "Declaration not in DeclNodes.def!"); -#define DECL(Derived, Base) case Derived: return #Derived; -#include "clang/AST/DeclNodes.def" + default: assert(0 && "Declaration not in DeclNodes.inc!"); +#define DECL(DERIVED, BASE) case DERIVED: return #DERIVED; +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" } } @@ -60,9 +62,10 @@ void Decl::setInvalidDecl(bool Invalid) { const char *DeclContext::getDeclKindName() const { switch (DeclKind) { - default: assert(0 && "Declaration context not in DeclNodes.def!"); -#define DECL(Derived, Base) case Decl::Derived: return #Derived; -#include "clang/AST/DeclNodes.def" + default: assert(0 && "Declaration context not in DeclNodes.inc!"); +#define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED; +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" } } @@ -75,28 +78,31 @@ void Decl::PrintStats() { fprintf(stderr, "*** Decl Stats:\n"); int totalDecls = 0; -#define DECL(Derived, Base) totalDecls += n##Derived##s; -#include "clang/AST/DeclNodes.def" +#define DECL(DERIVED, BASE) totalDecls += n##DERIVED##s; +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" fprintf(stderr, " %d decls total.\n", totalDecls); 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))); \ +#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))); \ } -#include "clang/AST/DeclNodes.def" +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" fprintf(stderr, "Total bytes = %d\n", totalBytes); } -void Decl::addDeclKind(Kind k) { +void Decl::add(Kind k) { switch (k) { - default: assert(0 && "Declaration not in DeclNodes.def!"); -#define DECL(Derived, Base) case Derived: ++n##Derived##s; break; -#include "clang/AST/DeclNodes.def" + default: assert(0 && "Declaration not in DeclNodes.inc!"); +#define DECL(DERIVED, BASE) case DERIVED: ++n##DERIVED##s; break; +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" } } @@ -206,17 +212,17 @@ ASTContext &Decl::getASTContext() const { return getTranslationUnitDecl()->getASTContext(); } -bool Decl::isUsed() const { +bool Decl::isUsed(bool CheckUsedAttr) const { if (Used) return true; // Check for used attribute. - if (hasAttr<UsedAttr>()) + if (CheckUsedAttr && hasAttr<UsedAttr>()) return true; // Check redeclarations for used attribute. for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { - if (I->hasAttr<UsedAttr>() || I->Used) + if ((CheckUsedAttr && I->hasAttr<UsedAttr>()) || I->Used) return true; } @@ -285,6 +291,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { // Never have names. case Friend: case FriendTemplate: + case AccessSpec: case LinkageSpec: case FileScopeAsm: case StaticAssert: @@ -307,9 +314,20 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { return 0; } +void Decl::initAttrs(Attr *attrs) { + assert(!HasAttrs && "Decl already contains attrs."); + + Attr *&AttrBlank = getASTContext().getDeclAttrs(this); + assert(AttrBlank == 0 && "HasAttrs was wrong?"); + + AttrBlank = attrs; + HasAttrs = true; +} + void Decl::addAttr(Attr *NewAttr) { Attr *&ExistingAttr = getASTContext().getDeclAttrs(this); + assert(NewAttr->getNext() == 0 && "Chain of attributes will be truncated!"); NewAttr->setNext(ExistingAttr); ExistingAttr = NewAttr; @@ -354,7 +372,6 @@ void Decl::swapAttrs(Decl *RHS) { RHS->HasAttrs = true; } - void Decl::Destroy(ASTContext &C) { // Free attributes for this decl. if (HasAttrs) { @@ -392,16 +409,18 @@ void Decl::Destroy(ASTContext &C) { Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); switch(DK) { -#define DECL_CONTEXT(Name) \ - case Decl::Name: \ - return static_cast<Name##Decl*>(const_cast<DeclContext*>(D)); -#define DECL_CONTEXT_BASE(Name) -#include "clang/AST/DeclNodes.def" +#define DECL(NAME, BASE) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ + return static_cast<NAME##Decl*>(const_cast<DeclContext*>(D)); +#define DECL_CONTEXT_BASE(NAME) +#include "clang/AST/DeclNodes.inc" default: -#define DECL_CONTEXT_BASE(Name) \ - if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \ - return static_cast<Name##Decl*>(const_cast<DeclContext*>(D)); -#include "clang/AST/DeclNodes.def" +#define DECL(NAME, BASE) +#define DECL_CONTEXT_BASE(NAME) \ + if (DK >= first##NAME && DK <= last##NAME) \ + return static_cast<NAME##Decl*>(const_cast<DeclContext*>(D)); +#include "clang/AST/DeclNodes.inc" assert(false && "a decl that inherits DeclContext isn't handled"); return 0; } @@ -410,46 +429,51 @@ Decl *Decl::castFromDeclContext (const DeclContext *D) { DeclContext *Decl::castToDeclContext(const Decl *D) { Decl::Kind DK = D->getKind(); switch(DK) { -#define DECL_CONTEXT(Name) \ - case Decl::Name: \ - return static_cast<Name##Decl*>(const_cast<Decl*>(D)); -#define DECL_CONTEXT_BASE(Name) -#include "clang/AST/DeclNodes.def" +#define DECL(NAME, BASE) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ + return static_cast<NAME##Decl*>(const_cast<Decl*>(D)); +#define DECL_CONTEXT_BASE(NAME) +#include "clang/AST/DeclNodes.inc" default: -#define DECL_CONTEXT_BASE(Name) \ - if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \ - return static_cast<Name##Decl*>(const_cast<Decl*>(D)); -#include "clang/AST/DeclNodes.def" +#define DECL(NAME, BASE) +#define DECL_CONTEXT_BASE(NAME) \ + if (DK >= first##NAME && DK <= last##NAME) \ + return static_cast<NAME##Decl*>(const_cast<Decl*>(D)); +#include "clang/AST/DeclNodes.inc" assert(false && "a decl that inherits DeclContext isn't handled"); return 0; } } -CompoundStmt* Decl::getCompoundBody() const { - return dyn_cast_or_null<CompoundStmt>(getBody()); -} - SourceLocation Decl::getBodyRBrace() const { - Stmt *Body = getBody(); - if (!Body) + // Special handling of FunctionDecl to avoid de-serializing the body from PCH. + // FunctionDecl stores EndRangeLoc for this purpose. + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) { + const FunctionDecl *Definition; + if (FD->hasBody(Definition)) + return Definition->getSourceRange().getEnd(); return SourceLocation(); - if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body)) - return CS->getRBracLoc(); - assert(isa<CXXTryStmt>(Body) && - "Body can only be CompoundStmt or CXXTryStmt"); - return cast<CXXTryStmt>(Body)->getSourceRange().getEnd(); + } + + if (Stmt *Body = getBody()) + return Body->getSourceRange().getEnd(); + + return SourceLocation(); } #ifndef NDEBUG void Decl::CheckAccessDeclContext() const { + // FIXME: Disable this until rdar://8146294 "access specifier for inner class + // templates is not set or checked" is fixed. + return; // Suppress this check if any of the following hold: // 1. this is the translation unit (and thus has no parent) // 2. this is a template parameter (and thus doesn't belong to its context) - // 3. this is a ParmVarDecl (which can be in a record context during - // the brief period between its creation and the creation of the - // FunctionDecl) - // 4. the context is not a record + // 3. the context is not a record + // 4. it's invalid if (isa<TranslationUnitDecl>(this) || + isa<TemplateTypeParmDecl>(this) || !isa<CXXRecordDecl>(getDeclContext()) || isInvalidDecl()) return; @@ -466,16 +490,18 @@ void Decl::CheckAccessDeclContext() const { bool DeclContext::classof(const Decl *D) { switch (D->getKind()) { -#define DECL_CONTEXT(Name) case Decl::Name: -#define DECL_CONTEXT_BASE(Name) -#include "clang/AST/DeclNodes.def" +#define DECL(NAME, BASE) +#define DECL_CONTEXT(NAME) case Decl::NAME: +#define DECL_CONTEXT_BASE(NAME) +#include "clang/AST/DeclNodes.inc" return true; default: -#define DECL_CONTEXT_BASE(Name) \ - if (D->getKind() >= Decl::Name##First && \ - D->getKind() <= Decl::Name##Last) \ +#define DECL(NAME, BASE) +#define DECL_CONTEXT_BASE(NAME) \ + if (D->getKind() >= Decl::first##NAME && \ + D->getKind() <= Decl::last##NAME) \ return true; -#include "clang/AST/DeclNodes.def" +#include "clang/AST/DeclNodes.inc" return false; } } @@ -537,7 +563,7 @@ bool DeclContext::isTransparentContext() const { return true; // FIXME: Check for C++0x scoped enums else if (DeclKind == Decl::LinkageSpec) return true; - else if (DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast) + else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord) return cast<RecordDecl>(this)->isAnonymousStructOrUnion(); else if (DeclKind == Decl::Namespace) return false; // FIXME: Check for C++0x inline namespaces @@ -581,7 +607,7 @@ DeclContext *DeclContext::getPrimaryContext() { return this; default: - if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) { + if (DeclKind >= Decl::firstTag && DeclKind <= Decl::lastTag) { // If this is a tag type that has a definition or is currently // being defined, that definition is our primary context. TagDecl *Tag = cast<TagDecl>(this); @@ -602,7 +628,7 @@ DeclContext *DeclContext::getPrimaryContext() { return Tag; } - assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast && + assert(DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction && "Unknown DeclContext kind"); return this; } @@ -626,9 +652,8 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); - llvm::SmallVector<uint32_t, 64> Decls; - if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this), - Decls)) + llvm::SmallVector<Decl*, 64> Decls; + if (Source->FindExternalLexicalDecls(this, Decls)) return; // There is no longer any lexical storage in this context @@ -642,7 +667,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { Decl *FirstNewDecl = 0; Decl *PrevDecl = 0; for (unsigned I = 0, N = Decls.size(); I != N; ++I) { - Decl *D = Source->GetDecl(Decls[I]); + Decl *D = Decls[I]; if (PrevDecl) PrevDecl->NextDeclInContext = D; else @@ -659,28 +684,83 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { LastDecl = PrevDecl; } -void -DeclContext::LoadVisibleDeclsFromExternalStorage() const { - DeclContext *This = const_cast<DeclContext *>(this); - ExternalASTSource *Source = getParentASTContext().getExternalSource(); - assert(hasExternalVisibleStorage() && Source && "No external storage?"); +DeclContext::lookup_result +ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name) { + ASTContext &Context = DC->getParentASTContext(); + StoredDeclsMap *Map; + if (!(Map = DC->LookupPtr)) + Map = DC->CreateStoredDeclsMap(Context); + + StoredDeclsList &List = (*Map)[Name]; + assert(List.isNull()); + (void) List; + + return DeclContext::lookup_result(); +} - llvm::SmallVector<VisibleDeclaration, 64> Decls; - if (Source->ReadDeclsVisibleInContext(This, Decls)) - return; +DeclContext::lookup_result +ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, + const VisibleDeclaration &VD) { + ASTContext &Context = DC->getParentASTContext(); + StoredDeclsMap *Map; + if (!(Map = DC->LookupPtr)) + Map = DC->CreateStoredDeclsMap(Context); + + StoredDeclsList &List = (*Map)[VD.Name]; + List.setFromDeclIDs(VD.Declarations); + return List.getLookupResult(Context); +} - // There is no longer any visible storage in this context - ExternalVisibleStorage = false; +DeclContext::lookup_result +ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl*> &Decls) { + ASTContext &Context = DC->getParentASTContext();; - // Load the declaration IDs for all of the names visible in this - // context. - assert(!LookupPtr && "Have a lookup map before de-serialization?"); - StoredDeclsMap *Map = CreateStoredDeclsMap(getParentASTContext()); + StoredDeclsMap *Map; + if (!(Map = DC->LookupPtr)) + Map = DC->CreateStoredDeclsMap(Context); + + StoredDeclsList &List = (*Map)[Name]; + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + if (List.isNull()) + List.setOnlyValue(Decls[I]); + else + List.AddSubsequentDecl(Decls[I]); + } + + return List.getLookupResult(Context); +} + +void ExternalASTSource::SetExternalVisibleDecls(const DeclContext *DC, + const llvm::SmallVectorImpl<VisibleDeclaration> &Decls) { + // There is no longer any visible storage in this context. + DC->ExternalVisibleStorage = false; + + assert(!DC->LookupPtr && "Have a lookup map before de-serialization?"); + StoredDeclsMap *Map = DC->CreateStoredDeclsMap(DC->getParentASTContext()); for (unsigned I = 0, N = Decls.size(); I != N; ++I) { (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations); } } +void ExternalASTSource::SetExternalVisibleDecls(const DeclContext *DC, + const llvm::SmallVectorImpl<NamedDecl*> &Decls) { + // There is no longer any visible storage in this context. + DC->ExternalVisibleStorage = false; + + assert(!DC->LookupPtr && "Have a lookup map before de-serialization?"); + StoredDeclsMap &Map = *DC->CreateStoredDeclsMap(DC->getParentASTContext()); + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + StoredDeclsList &List = Map[Decls[I]->getDeclName()]; + if (List.isNull()) + List.setOnlyValue(Decls[I]); + else + List.AddSubsequentDecl(Decls[I]); + } +} + DeclContext::decl_iterator DeclContext::decls_begin() const { if (hasExternalLexicalStorage()) LoadLexicalDeclsFromExternalStorage(); @@ -801,8 +881,17 @@ DeclContext::lookup(DeclarationName Name) { if (PrimaryContext != this) return PrimaryContext->lookup(Name); - if (hasExternalVisibleStorage()) - LoadVisibleDeclsFromExternalStorage(); + if (hasExternalVisibleStorage()) { + // Check to see if we've already cached the lookup results. + if (LookupPtr) { + StoredDeclsMap::iterator I = LookupPtr->find(Name); + if (I != LookupPtr->end()) + return I->second.getLookupResult(getParentASTContext()); + } + + ExternalASTSource *Source = getParentASTContext().getExternalSource(); + return Source->FindExternalVisibleDeclsByName(this, Name); + } /// If there is no lookup data structure, build one now by walking /// all of the linked DeclContexts (in declaration order!) and @@ -858,9 +947,10 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) { } // If we already have a lookup data structure, perform the insertion - // into it. Otherwise, be lazy and don't build that structure until - // someone asks for it. - if (LookupPtr || !Recoverable) + // into it. If we haven't deserialized externally stored decls, deserialize + // them so we can add the decl. Otherwise, be lazy and don't build that + // structure until someone asks for it. + if (LookupPtr || !Recoverable || hasExternalVisibleStorage()) makeDeclVisibleInContextImpl(D); // If we are a transparent context, insert into our parent context, @@ -880,6 +970,12 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) { if (isa<ClassTemplateSpecializationDecl>(D)) return; + // If there is an external AST source, load any declarations it knows about + // with this declaration's name. + if (ExternalASTSource *Source = getParentASTContext().getExternalSource()) + if (hasExternalVisibleStorage()) + Source->FindExternalVisibleDeclsByName(this, D->getDeclName()); + ASTContext *C = 0; if (!LookupPtr) { C = &getParentASTContext(); @@ -932,7 +1028,7 @@ void StoredDeclsList::materializeDecls(ASTContext &Context) { ExternalASTSource *Source = Context.getExternalSource(); assert(Source && "No external AST source available!"); - Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID)); + Data = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(DeclID)); break; } @@ -944,7 +1040,7 @@ void StoredDeclsList::materializeDecls(ASTContext &Context) { assert(Source && "No external AST source available!"); for (unsigned I = 0, N = Vector.size(); I != N; ++I) - Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I])); + Vector[I] = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(Vector[I])); Data = (Data & ~0x03) | DK_Decl_Vector; break; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index cd7afd9..dd0fe08 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -32,6 +32,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) Abstract(false), HasTrivialConstructor(true), HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true), HasTrivialDestructor(true), ComputedVisibleConversions(false), + DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), + DeclaredCopyAssignment(false), DeclaredDestructor(false), Bases(0), NumBases(0), VBases(0), NumVBases(0), Definition(D), FirstFriend(0) { } @@ -58,6 +60,11 @@ CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, return R; } +CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), 0, 0, + SourceLocation()); +} + CXXRecordDecl::~CXXRecordDecl() { } @@ -159,6 +166,29 @@ bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { return getCopyConstructor(Context, Qualifiers::Const) != 0; } +/// \brief Perform a simplistic form of overload resolution that only considers +/// cv-qualifiers on a single parameter, and return the best overload candidate +/// (if there is one). +static CXXMethodDecl * +GetBestOverloadCandidateSimple( + const llvm::SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) { + if (Cands.empty()) + return 0; + if (Cands.size() == 1) + return Cands[0].first; + + unsigned Best = 0, N = Cands.size(); + for (unsigned I = 1; I != N; ++I) + if (Cands[Best].second.isSupersetOf(Cands[I].second)) + Best = I; + + for (unsigned I = 1; I != N; ++I) + if (Cands[Best].second.isSupersetOf(Cands[I].second)) + return 0; + + return Cands[Best].first; +} + CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, unsigned TypeQuals) const{ QualType ClassType @@ -167,6 +197,7 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); unsigned FoundTQs; + llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; DeclContext::lookup_const_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); Con != ConEnd; ++Con) { @@ -175,61 +206,68 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, if (isa<FunctionTemplateDecl>(*Con)) continue; - if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(FoundTQs)) { + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); + if (Constructor->isCopyConstructor(FoundTQs)) { if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) || (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const))) - return cast<CXXConstructorDecl>(*Con); - + Found.push_back(std::make_pair( + const_cast<CXXConstructorDecl *>(Constructor), + Qualifiers::fromCVRMask(FoundTQs))); } } - return 0; + + return cast_or_null<CXXConstructorDecl>( + GetBestOverloadCandidateSimple(Found)); } -bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context, - const CXXMethodDecl *& MD) const { - QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( - const_cast<CXXRecordDecl*>(this))); - DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal); - +CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { + ASTContext &Context = getASTContext(); + QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this)); + DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); + + llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; DeclContext::lookup_const_iterator Op, OpEnd; - for (llvm::tie(Op, OpEnd) = this->lookup(OpName); - Op != OpEnd; ++Op) { + for (llvm::tie(Op, OpEnd) = this->lookup(Name); Op != OpEnd; ++Op) { // C++ [class.copy]p9: // A user-declared copy assignment operator is a non-static non-template // member function of class X with exactly one parameter of type X, X&, // const X&, volatile X& or const volatile X&. const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op); - if (!Method) + if (!Method || Method->isStatic() || Method->getPrimaryTemplate()) continue; - - if (Method->isStatic()) - continue; - if (Method->getPrimaryTemplate()) - continue; - const FunctionProtoType *FnType = - Method->getType()->getAs<FunctionProtoType>(); + + const FunctionProtoType *FnType + = Method->getType()->getAs<FunctionProtoType>(); assert(FnType && "Overloaded operator has no prototype."); // Don't assert on this; an invalid decl might have been left in the AST. if (FnType->getNumArgs() != 1 || FnType->isVariadic()) continue; - bool AcceptsConst = true; + QualType ArgType = FnType->getArgType(0); + Qualifiers Quals; if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()) { ArgType = Ref->getPointeeType(); - // Is it a non-const lvalue reference? - if (!ArgType.isConstQualified()) - AcceptsConst = false; + // If we have a const argument and we have a reference to a non-const, + // this function does not match. + if (ArgIsConst && !ArgType.isConstQualified()) + continue; + + Quals = ArgType.getQualifiers(); + } else { + // By-value copy-assignment operators are treated like const X& + // copy-assignment operators. + Quals = Qualifiers::fromCVRMask(Qualifiers::Const); } - if (!Context.hasSameUnqualifiedType(ArgType, ClassType)) + + if (!Context.hasSameUnqualifiedType(ArgType, Class)) continue; - MD = Method; - // We have a single argument of type cv X or cv X&, i.e. we've found the - // copy assignment operator. Return whether it accepts const arguments. - return AcceptsConst; + + // Save this copy-assignment operator. It might be "the one". + Found.push_back(std::make_pair(const_cast<CXXMethodDecl *>(Method), Quals)); } - assert(isInvalidDecl() && - "No copy assignment operator declared in valid code."); - return false; + + // Use a simplistic form of overload resolution to find the candidate. + return GetBestOverloadCandidateSimple(Found); } void @@ -239,6 +277,9 @@ CXXRecordDecl::addedConstructor(ASTContext &Context, // Note that we have a user-declared constructor. data().UserDeclaredConstructor = true; + // Note that we have no need of an implicitly-declared default constructor. + data().DeclaredDefaultConstructor = true; + // C++ [dcl.init.aggr]p1: // An aggregate is an array or a class (clause 9) with no // user-declared constructors (12.1) [...]. @@ -258,11 +299,13 @@ CXXRecordDecl::addedConstructor(ASTContext &Context, // suppress the implicit declaration of a copy constructor. if (ConDecl->isCopyConstructor()) { data().UserDeclaredCopyConstructor = true; - + data().DeclaredCopyConstructor = true; + // C++ [class.copy]p6: // A copy constructor is trivial if it is implicitly declared. // FIXME: C++0x: don't do this for "= default" copy constructors. data().HasTrivialCopyConstructor = false; + } } @@ -294,7 +337,8 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context, // Suppress the implicit declaration of a copy constructor. data().UserDeclaredCopyAssignment = true; - + data().DeclaredCopyAssignment = true; + // C++ [class.copy]p11: // A copy assignment operator is trivial if it is implicitly declared. // FIXME: C++0x: don't do this for "= default" copy operators. @@ -546,7 +590,8 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { } CXXConstructorDecl * -CXXRecordDecl::getDefaultConstructor(ASTContext &Context) { +CXXRecordDecl::getDefaultConstructor() { + ASTContext &Context = getASTContext(); QualType ClassType = Context.getTypeDeclType(this); DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( @@ -566,7 +611,8 @@ CXXRecordDecl::getDefaultConstructor(ASTContext &Context) { return 0; } -CXXDestructorDecl *CXXRecordDecl::getDestructor(ASTContext &Context) const { +CXXDestructorDecl *CXXRecordDecl::getDestructor() const { + ASTContext &Context = getASTContext(); QualType ClassType = Context.getTypeDeclType(this); DeclarationName Name @@ -670,6 +716,10 @@ CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const { return getASTContext().overridden_methods_end(this); } +unsigned CXXMethodDecl::size_overridden_methods() const { + return getASTContext().overridden_methods_size(this); +} + QualType CXXMethodDecl::getThisType(ASTContext &C) const { // C++ 9.3.2p1: The type of this in a member function of a class X is X*. // If the member function is declared const, the type of this is const X*, @@ -693,7 +743,7 @@ bool CXXMethodDecl::hasInlineBody() const { CheckFn = this; const FunctionDecl *fn; - return CheckFn->getBody(fn) && !fn->isOutOfLine(); + return CheckFn->hasBody(fn) && !fn->isOutOfLine(); } CXXBaseOrMemberInitializer:: diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp index ab3552d..99bfe40 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp @@ -39,3 +39,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, cast<CXXRecordDecl>(DC)->pushFriendDecl(FD); return FD; } + +FriendDecl *FriendDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) FriendDecl(Empty); +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index dc4aacd..adb0e7d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -223,17 +223,24 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C); } -/// getClassExtension - Find class extension of the given class. -// FIXME. can speed it up, if need be. -ObjCCategoryDecl* ObjCInterfaceDecl::getClassExtension() const { - const ObjCInterfaceDecl* ClassDecl = this; - for (ObjCCategoryDecl *CDecl = ClassDecl->getCategoryList(); CDecl; +/// getFirstClassExtension - Find first class extension of the given class. +ObjCCategoryDecl* ObjCInterfaceDecl::getFirstClassExtension() const { + for (ObjCCategoryDecl *CDecl = getCategoryList(); CDecl; CDecl = CDecl->getNextClassCategory()) if (CDecl->IsClassExtension()) return CDecl; return 0; } +/// getNextClassCategory - Find next class extension in list of categories. +const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const { + for (const ObjCCategoryDecl *CDecl = getNextClassCategory(); CDecl; + CDecl = CDecl->getNextClassCategory()) + if (CDecl->IsClassExtension()) + return CDecl; + return 0; +} + ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) { ObjCInterfaceDecl* ClassDecl = this; @@ -242,11 +249,13 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, clsDeclared = ClassDecl; return I; } - if (const ObjCCategoryDecl *CDecl = ClassDecl->getClassExtension()) + for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension(); + CDecl; CDecl = CDecl->getNextClassExtension()) { if (ObjCIvarDecl *I = CDecl->getIvarDecl(ID)) { clsDeclared = ClassDecl; return I; } + } ClassDecl = ClassDecl->getSuperClass(); } @@ -887,7 +896,7 @@ ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation AtLoc, - QualType T, + TypeSourceInfo *T, PropertyControl propControl) { return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 53949247..765772d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -183,7 +183,7 @@ void DeclPrinter::Print(AccessSpecifier AS) { case AS_none: assert(0 && "No access specifier!"); break; case AS_public: Out << "public"; break; case AS_protected: Out << "protected"; break; - case AS_private: Out << " private"; break; + case AS_private: Out << "private"; break; } } @@ -195,9 +195,6 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (Indent) Indentation += Policy.Indentation; - bool PrintAccess = isa<CXXRecordDecl>(DC); - AccessSpecifier CurAS = AS_none; - llvm::SmallVector<Decl*, 2> Decls; for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); D != DEnd; ++D) { @@ -205,21 +202,14 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { // Skip over implicit declarations in pretty-printing mode. if (D->isImplicit()) continue; // FIXME: Ugly hack so we don't pretty-print the builtin declaration - // of __builtin_va_list. There should be some other way to check that. - if (isa<NamedDecl>(*D) && cast<NamedDecl>(*D)->getNameAsString() == - "__builtin_va_list") - continue; - } - - if (PrintAccess) { - AccessSpecifier AS = D->getAccess(); - - if (AS != CurAS) { - if (Indent) - this->Indent(Indentation - Policy.Indentation); - Print(AS); - Out << ":\n"; - CurAS = AS; + // of __builtin_va_list or __[u]int128_t. There should be some other way + // to check that. + if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { + if (IdentifierInfo *II = ND->getIdentifier()) { + if (II->isStr("__builtin_va_list") || + II->isStr("__int128_t") || II->isStr("__uint128_t")) + continue; + } } } @@ -251,6 +241,16 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { Decls.push_back(*D); continue; } + + if (isa<AccessSpecDecl>(*D)) { + Indentation -= Policy.Indentation; + this->Indent(); + Print(D->getAccess()); + Out << ":\n"; + Indentation += Policy.Indentation; + continue; + } + this->Indent(); Visit(*D); @@ -406,7 +406,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { FieldDecl *FD = BMInitializer->getMember(); Out << FD; } else { - Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(); + Out << QualType(BMInitializer->getBaseClass(), + 0).getAsString(Policy); } Out << "("; @@ -653,7 +654,11 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { Out << "> "; - Visit(D->getTemplatedDecl()); + if (isa<TemplateTemplateParmDecl>(D)) { + Out << "class " << D->getName(); + } else { + Visit(D->getTemplatedDecl()); + } } //---------------------------------------------------------------------------- diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index 26e291c..9e1d79d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -162,37 +162,19 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, TemplateParameterList *Params, NamedDecl *Decl, ClassTemplateDecl *PrevDecl) { - Common *CommonPtr; - if (PrevDecl) - CommonPtr = PrevDecl->CommonPtr; - else { - CommonPtr = new (C) Common; - C.AddDeallocation(DeallocateCommon, CommonPtr); - } - - return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl, - CommonPtr); -} - -ClassTemplateDecl::~ClassTemplateDecl() { - assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed"); + ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl); + New->setPreviousDeclaration(PrevDecl); + return New; } void ClassTemplateDecl::Destroy(ASTContext& C) { - if (!PreviousDeclaration) { - CommonPtr->~Common(); - C.Deallocate((void*)CommonPtr); - } - CommonPtr = 0; - - this->~ClassTemplateDecl(); - C.Deallocate((void*)this); + Decl::Destroy(C); } void ClassTemplateDecl::getPartialSpecializations( llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) { llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &PartialSpecs - = CommonPtr->PartialSpecializations; + = getPartialSpecializations(); PS.clear(); PS.resize(PartialSpecs.size()); for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator @@ -219,7 +201,8 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) { } QualType -ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) { +ClassTemplateDecl::getInjectedClassNameSpecialization() { + Common *CommonPtr = getCommonPtr(); if (!CommonPtr->InjectedClassNameType.isNull()) return CommonPtr->InjectedClassNameType; @@ -227,7 +210,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) { // corresponding to template parameter packs should be pack // expansions. We already say that in 14.6.2.1p2, so it would be // better to fix that redundancy. - + ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); llvm::SmallVector<TemplateArgument, 16> TemplateArgs; TemplateArgs.reserve(Params->size()); @@ -240,7 +223,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) { } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { Expr *E = new (Context) DeclRefExpr(NTTP, - NTTP->getType().getNonReferenceType(), + NTTP->getType().getNonLValueExprType(Context), NTTP->getLocation()); TemplateArgs.push_back(TemplateArgument(E)); } else { @@ -256,6 +239,20 @@ ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) { return CommonPtr->InjectedClassNameType; } +ClassTemplateDecl::Common *ClassTemplateDecl::getCommonPtr() { + // Find the first declaration of this function template. + ClassTemplateDecl *First = this; + while (First->getPreviousDeclaration()) + First = First->getPreviousDeclaration(); + + if (First->CommonOrPrev.isNull()) { + Common *CommonPtr = new (getASTContext()) Common; + getASTContext().AddDeallocation(DeallocateCommon, CommonPtr); + First->CommonOrPrev = CommonPtr; + } + return First->CommonOrPrev.get<Common*>(); +} + //===----------------------------------------------------------------------===// // TemplateTypeParm Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// @@ -269,6 +266,12 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack); } +TemplateTypeParmDecl * +TemplateTypeParmDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) TemplateTypeParmDecl(0, SourceLocation(), 0, false, + QualType(), false); +} + SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { return DefaultArgument->getTypeLoc().getSourceRange().getBegin(); } @@ -294,8 +297,9 @@ NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, } SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { - return DefaultArgument? DefaultArgument->getSourceRange().getBegin() - : SourceLocation(); + return hasDefaultArgument() + ? getDefaultArgument()->getSourceRange().getBegin() + : SourceLocation(); } //===----------------------------------------------------------------------===// @@ -393,6 +397,13 @@ TemplateArgumentList::TemplateArgumentList(ASTContext &Context, } } +TemplateArgumentList::TemplateArgumentList(ASTContext &Context, + const TemplateArgument *Args, + unsigned NumArgs) + : NumFlatArguments(0), NumStructuredArguments(0) { + init(Context, Args, NumArgs); +} + /// Produces a shallow copy of the given template argument list. This /// assumes that the input argument list outlives it. This takes the list as /// a pointer to avoid looking like a copy constructor, since this really @@ -403,6 +414,23 @@ TemplateArgumentList::TemplateArgumentList(const TemplateArgumentList *Other) StructuredArguments(Other->StructuredArguments.getPointer(), false), NumStructuredArguments(Other->NumStructuredArguments) { } +void TemplateArgumentList::init(ASTContext &Context, + const TemplateArgument *Args, + unsigned NumArgs) { +assert(NumFlatArguments == 0 && NumStructuredArguments == 0 && + "Already initialized!"); + +NumFlatArguments = NumStructuredArguments = NumArgs; +TemplateArgument *NewArgs = new (Context) TemplateArgument[NumArgs]; +std::copy(Args, Args+NumArgs, NewArgs); +FlatArguments.setPointer(NewArgs); +FlatArguments.setInt(1); // Owns the pointer. + +// Just reuse the flat arguments array. +StructuredArguments.setPointer(NewArgs); +StructuredArguments.setInt(0); // Doesn't own the pointer. +} + void TemplateArgumentList::Destroy(ASTContext &C) { if (FlatArguments.getInt()) C.Deallocate((void*)FlatArguments.getPointer()); @@ -425,11 +453,17 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), - TypeAsWritten(0), + ExplicitInfo(0), TemplateArgs(Context, Builder, /*TakeArgs=*/true), SpecializationKind(TSK_Undeclared) { } +ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(Kind DK) + : CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), 0, 0), + ExplicitInfo(0), + SpecializationKind(TSK_Undeclared) { +} + ClassTemplateSpecializationDecl * ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, @@ -447,7 +481,15 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, return Result; } +ClassTemplateSpecializationDecl * +ClassTemplateSpecializationDecl::Create(ASTContext &Context, EmptyShell Empty) { + return + new (Context)ClassTemplateSpecializationDecl(ClassTemplateSpecialization); +} + void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) { + delete ExplicitInfo; + if (SpecializedPartialSpecialization *PartialSpec = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) C.Deallocate(PartialSpec); @@ -508,6 +550,25 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, return Result; } +ClassTemplatePartialSpecializationDecl * +ClassTemplatePartialSpecializationDecl::Create(ASTContext &Context, + EmptyShell Empty) { + return new (Context)ClassTemplatePartialSpecializationDecl(); +} + +void ClassTemplatePartialSpecializationDecl:: +initTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgInfos) { + assert(ArgsAsWritten == 0 && "ArgsAsWritten already set"); + unsigned N = ArgInfos.size(); + TemplateArgumentLoc *ClonedArgs + = new (getASTContext()) TemplateArgumentLoc[N]; + for (unsigned I = 0; I != N; ++I) + ClonedArgs[I] = ArgInfos[I]; + + ArgsAsWritten = ClonedArgs; + NumArgsAsWritten = N; +} + //===----------------------------------------------------------------------===// // FriendTemplateDecl Implementation //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index c38cec3..6524a31 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -37,7 +37,7 @@ bool Expr::isKnownToHaveBooleanValue() const { // If this value has _Bool type, it is obvious 0/1. if (getType()->isBooleanType()) return true; // If this is a non-scalar-integer type, we don't care enough to try. - if (!getType()->isIntegralType()) return false; + if (!getType()->isIntegralOrEnumerationType()) return false; if (const ParenExpr *PE = dyn_cast<ParenExpr>(this)) return PE->getSubExpr()->isKnownToHaveBooleanValue(); @@ -52,7 +52,9 @@ bool Expr::isKnownToHaveBooleanValue() const { } } - if (const CastExpr *CE = dyn_cast<CastExpr>(this)) + // Only look through implicit casts. If the user writes + // '(int) (a && b)' treat it as an arbitrary int. + if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(this)) return CE->getSubExpr()->isKnownToHaveBooleanValue(); if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(this)) { @@ -111,10 +113,14 @@ void ExplicitTemplateArgumentList::copyInto( Info.addArgument(getTemplateArgs()[I]); } +std::size_t ExplicitTemplateArgumentList::sizeFor(unsigned NumTemplateArgs) { + return sizeof(ExplicitTemplateArgumentList) + + sizeof(TemplateArgumentLoc) * NumTemplateArgs; +} + std::size_t ExplicitTemplateArgumentList::sizeFor( const TemplateArgumentListInfo &Info) { - return sizeof(ExplicitTemplateArgumentList) + - sizeof(TemplateArgumentLoc) * Info.size(); + return sizeFor(Info.size()); } void DeclRefExpr::computeDependence() { @@ -158,7 +164,7 @@ void DeclRefExpr::computeDependence() { // (VD) - a constant with integral or enumeration type and is // initialized with an expression that is value-dependent. else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { - if (Var->getType()->isIntegralType() && + if (Var->getType()->isIntegralOrEnumerationType() && Var->getType().getCVRQualifiers() == Qualifiers::Const) { if (const Expr *Init = Var->getAnyInitializer()) if (Init->isValueDependent()) @@ -222,6 +228,19 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, TemplateArgs, T); } +DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier, + unsigned NumTemplateArgs) { + std::size_t Size = sizeof(DeclRefExpr); + if (HasQualifier) + Size += sizeof(NameQualifier); + + if (NumTemplateArgs) + Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + + void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>()); + return new (Mem) DeclRefExpr(EmptyShell()); +} + SourceRange DeclRefExpr::getSourceRange() const { // FIXME: Does not handle multi-token names well, e.g., operator[]. SourceRange R(Loc); @@ -557,7 +576,10 @@ QualType CallExpr::getCallReturnType() const { CalleeType = FnTypePtr->getPointeeType(); else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>()) CalleeType = BPT->getPointeeType(); - + else if (const MemberPointerType *MPT + = CalleeType->getAs<MemberPointerType>()) + CalleeType = MPT->getPointeeType(); + const FunctionType *FnType = CalleeType->getAs<FunctionType>(); return FnType->getResultType(); } @@ -662,6 +684,8 @@ const char *CastExpr::getCastKindName() const { return "Unknown"; case CastExpr::CK_BitCast: return "BitCast"; + case CastExpr::CK_LValueBitCast: + return "LValueBitCast"; case CastExpr::CK_NoOp: return "NoOp"; case CastExpr::CK_BaseToDerived: @@ -968,7 +992,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, switch (BO->getOpcode()) { default: break; - // Consider ',', '||', '&&' to have side effects if the LHS or RHS does. + // Consider the RHS of comma for side effects. LHS was checked by + // Sema::CheckCommaOperands. case BinaryOperator::Comma: // ((foo = <blah>), 0) is an idiom for hiding the result (and // lvalue-ness) of an assignment written in a macro. @@ -976,10 +1001,14 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, dyn_cast<IntegerLiteral>(BO->getRHS()->IgnoreParens())) if (IE->getValue() == 0) return false; + return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx); + // Consider '||', '&&' to have side effects if the LHS or RHS does. case BinaryOperator::LAnd: case BinaryOperator::LOr: - return (BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) || - BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); + if (!BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) || + !BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx)) + return false; + break; } if (BO->isAssignmentOp()) return false; @@ -1140,378 +1169,6 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, } } -/// DeclCanBeLvalue - Determine whether the given declaration can be -/// an lvalue. This is a helper routine for isLvalue. -static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) { - // C++ [temp.param]p6: - // A non-type non-reference template-parameter is not an lvalue. - if (const NonTypeTemplateParmDecl *NTTParm - = dyn_cast<NonTypeTemplateParmDecl>(Decl)) - return NTTParm->getType()->isReferenceType(); - - return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) || - // C++ 3.10p2: An lvalue refers to an object or function. - (Ctx.getLangOptions().CPlusPlus && - (isa<FunctionDecl>(Decl) || isa<FunctionTemplateDecl>(Decl))); -} - -/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or an -/// incomplete type other than void. Nonarray expressions that can be lvalues: -/// - name, where name must be a variable -/// - e[i] -/// - (e), where e must be an lvalue -/// - e.name, where e must be an lvalue -/// - e->name -/// - *e, the type of e cannot be a function type -/// - string-constant -/// - (__real__ e) and (__imag__ e) where e is an lvalue [GNU extension] -/// - reference type [C++ [expr]] -/// -Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { - assert(!TR->isReferenceType() && "Expressions can't have reference type."); - - isLvalueResult Res = isLvalueInternal(Ctx); - if (Res != LV_Valid || Ctx.getLangOptions().CPlusPlus) - return Res; - - // first, check the type (C99 6.3.2.1). Expressions with function - // type in C are not lvalues, but they can be lvalues in C++. - if (TR->isFunctionType() || TR == Ctx.OverloadTy) - return LV_NotObjectType; - - // Allow qualified void which is an incomplete type other than void (yuck). - if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers()) - return LV_IncompleteVoidType; - - return LV_Valid; -} - -// Check whether the expression can be sanely treated like an l-value -Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { - switch (getStmtClass()) { - case ObjCIsaExprClass: - case StringLiteralClass: // C99 6.5.1p4 - case ObjCEncodeExprClass: // @encode behaves like its string in every way. - return LV_Valid; - case ArraySubscriptExprClass: // C99 6.5.3p4 (e1[e2] == (*((e1)+(e2)))) - // For vectors, make sure base is an lvalue (i.e. not a function call). - if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType()) - return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx); - return LV_Valid; - case DeclRefExprClass: { // C99 6.5.1p2 - const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl(); - if (DeclCanBeLvalue(RefdDecl, Ctx)) - return LV_Valid; - break; - } - case BlockDeclRefExprClass: { - const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(this); - if (isa<VarDecl>(BDR->getDecl())) - return LV_Valid; - break; - } - case MemberExprClass: { - const MemberExpr *m = cast<MemberExpr>(this); - if (Ctx.getLangOptions().CPlusPlus) { // C++ [expr.ref]p4: - NamedDecl *Member = m->getMemberDecl(); - // C++ [expr.ref]p4: - // If E2 is declared to have type "reference to T", then E1.E2 - // is an lvalue. - if (ValueDecl *Value = dyn_cast<ValueDecl>(Member)) - if (Value->getType()->isReferenceType()) - return LV_Valid; - - // -- If E2 is a static data member [...] then E1.E2 is an lvalue. - if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord()) - return LV_Valid; - - // -- If E2 is a non-static data member [...]. If E1 is an - // lvalue, then E1.E2 is an lvalue. - if (isa<FieldDecl>(Member)) { - if (m->isArrow()) - return LV_Valid; - return m->getBase()->isLvalue(Ctx); - } - - // -- If it refers to a static member function [...], then - // E1.E2 is an lvalue. - // -- Otherwise, if E1.E2 refers to a non-static member - // function [...], then E1.E2 is not an lvalue. - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) - return Method->isStatic()? LV_Valid : LV_MemberFunction; - - // -- If E2 is a member enumerator [...], the expression E1.E2 - // is not an lvalue. - if (isa<EnumConstantDecl>(Member)) - return LV_InvalidExpression; - - // Not an lvalue. - return LV_InvalidExpression; - } - - // C99 6.5.2.3p4 - if (m->isArrow()) - return LV_Valid; - Expr *BaseExp = m->getBase(); - if (BaseExp->getStmtClass() == ObjCPropertyRefExprClass || - BaseExp->getStmtClass() == ObjCImplicitSetterGetterRefExprClass) - return LV_SubObjCPropertySetting; - return - BaseExp->isLvalue(Ctx); - } - case UnaryOperatorClass: - if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Deref) - return LV_Valid; // C99 6.5.3p4 - - if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Real || - cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Imag || - cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Extension) - return cast<UnaryOperator>(this)->getSubExpr()->isLvalue(Ctx); // GNU. - - if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.pre.incr]p1 - (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::PreInc || - cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::PreDec)) - return LV_Valid; - break; - case ImplicitCastExprClass: - if (cast<ImplicitCastExpr>(this)->isLvalueCast()) - return LV_Valid; - - // If this is a conversion to a class temporary, make a note of - // that. - if (Ctx.getLangOptions().CPlusPlus && getType()->isRecordType()) - return LV_ClassTemporary; - - break; - case ParenExprClass: // C99 6.5.1p5 - return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx); - case BinaryOperatorClass: - case CompoundAssignOperatorClass: { - const BinaryOperator *BinOp = cast<BinaryOperator>(this); - - if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.comma]p1 - BinOp->getOpcode() == BinaryOperator::Comma) - return BinOp->getRHS()->isLvalue(Ctx); - - // C++ [expr.mptr.oper]p6 - // The result of a .* expression is an lvalue only if its first operand is - // an lvalue and its second operand is a pointer to data member. - if (BinOp->getOpcode() == BinaryOperator::PtrMemD && - !BinOp->getType()->isFunctionType()) - return BinOp->getLHS()->isLvalue(Ctx); - - // The result of an ->* expression is an lvalue only if its second operand - // is a pointer to data member. - if (BinOp->getOpcode() == BinaryOperator::PtrMemI && - !BinOp->getType()->isFunctionType()) { - QualType Ty = BinOp->getRHS()->getType(); - if (Ty->isMemberPointerType() && !Ty->isMemberFunctionPointerType()) - return LV_Valid; - } - - if (!BinOp->isAssignmentOp()) - return LV_InvalidExpression; - - if (Ctx.getLangOptions().CPlusPlus) - // C++ [expr.ass]p1: - // The result of an assignment operation [...] is an lvalue. - return LV_Valid; - - - // C99 6.5.16: - // An assignment expression [...] is not an lvalue. - return LV_InvalidExpression; - } - case CallExprClass: - case CXXOperatorCallExprClass: - case CXXMemberCallExprClass: { - // C++0x [expr.call]p10 - // A function call is an lvalue if and only if the result type - // is an lvalue reference. - QualType ReturnType = cast<CallExpr>(this)->getCallReturnType(); - if (ReturnType->isLValueReferenceType()) - return LV_Valid; - - // If the function is returning a class temporary, make a note of - // that. - if (Ctx.getLangOptions().CPlusPlus && ReturnType->isRecordType()) - return LV_ClassTemporary; - - break; - } - case CompoundLiteralExprClass: // C99 6.5.2.5p5 - // FIXME: Is this what we want in C++? - return LV_Valid; - case ChooseExprClass: - // __builtin_choose_expr is an lvalue if the selected operand is. - return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx)->isLvalue(Ctx); - case ExtVectorElementExprClass: - if (cast<ExtVectorElementExpr>(this)->containsDuplicateElements()) - return LV_DuplicateVectorComponents; - return LV_Valid; - case ObjCIvarRefExprClass: // ObjC instance variables are lvalues. - return LV_Valid; - case ObjCPropertyRefExprClass: // FIXME: check if read-only property. - return LV_Valid; - case ObjCImplicitSetterGetterRefExprClass: - // FIXME: check if read-only property. - return LV_Valid; - case PredefinedExprClass: - return LV_Valid; - case UnresolvedLookupExprClass: - case UnresolvedMemberExprClass: - return LV_Valid; - case CXXDefaultArgExprClass: - return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx); - case CStyleCastExprClass: - case CXXFunctionalCastExprClass: - case CXXStaticCastExprClass: - case CXXDynamicCastExprClass: - case CXXReinterpretCastExprClass: - case CXXConstCastExprClass: - // The result of an explicit cast is an lvalue if the type we are - // casting to is an lvalue reference type. See C++ [expr.cast]p1, - // C++ [expr.static.cast]p2, C++ [expr.dynamic.cast]p2, - // C++ [expr.reinterpret.cast]p1, C++ [expr.const.cast]p1. - if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()-> - isLValueReferenceType()) - return LV_Valid; - - // If this is a conversion to a class temporary, make a note of - // that. - if (Ctx.getLangOptions().CPlusPlus && - cast<ExplicitCastExpr>(this)->getTypeAsWritten()->isRecordType()) - return LV_ClassTemporary; - - break; - case CXXTypeidExprClass: - // C++ 5.2.8p1: The result of a typeid expression is an lvalue of ... - return LV_Valid; - case CXXBindTemporaryExprClass: - return cast<CXXBindTemporaryExpr>(this)->getSubExpr()-> - isLvalueInternal(Ctx); - case CXXBindReferenceExprClass: - // Something that's bound to a reference is always an lvalue. - return LV_Valid; - case ConditionalOperatorClass: { - // Complicated handling is only for C++. - if (!Ctx.getLangOptions().CPlusPlus) - return LV_InvalidExpression; - - // Sema should have taken care to ensure that a CXXTemporaryObjectExpr is - // everywhere there's an object converted to an rvalue. Also, any other - // casts should be wrapped by ImplicitCastExprs. There's just the special - // case involving throws to work out. - const ConditionalOperator *Cond = cast<ConditionalOperator>(this); - Expr *True = Cond->getTrueExpr(); - Expr *False = Cond->getFalseExpr(); - // C++0x 5.16p2 - // If either the second or the third operand has type (cv) void, [...] - // the result [...] is an rvalue. - if (True->getType()->isVoidType() || False->getType()->isVoidType()) - return LV_InvalidExpression; - - // Both sides must be lvalues for the result to be an lvalue. - if (True->isLvalue(Ctx) != LV_Valid || False->isLvalue(Ctx) != LV_Valid) - return LV_InvalidExpression; - - // That's it. - return LV_Valid; - } - - case Expr::CXXExprWithTemporariesClass: - return cast<CXXExprWithTemporaries>(this)->getSubExpr()->isLvalue(Ctx); - - case Expr::ObjCMessageExprClass: - if (const ObjCMethodDecl *Method - = cast<ObjCMessageExpr>(this)->getMethodDecl()) - if (Method->getResultType()->isLValueReferenceType()) - return LV_Valid; - break; - - case Expr::CXXConstructExprClass: - case Expr::CXXTemporaryObjectExprClass: - case Expr::CXXZeroInitValueExprClass: - return LV_ClassTemporary; - - default: - break; - } - return LV_InvalidExpression; -} - -/// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, -/// does not have an incomplete type, does not have a const-qualified type, and -/// if it is a structure or union, does not have any member (including, -/// recursively, any member or element of all contained aggregates or unions) -/// with a const-qualified type. -Expr::isModifiableLvalueResult -Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { - isLvalueResult lvalResult = isLvalue(Ctx); - - switch (lvalResult) { - case LV_Valid: - // C++ 3.10p11: Functions cannot be modified, but pointers to - // functions can be modifiable. - if (Ctx.getLangOptions().CPlusPlus && TR->isFunctionType()) - return MLV_NotObjectType; - break; - - case LV_NotObjectType: return MLV_NotObjectType; - case LV_IncompleteVoidType: return MLV_IncompleteVoidType; - case LV_DuplicateVectorComponents: return MLV_DuplicateVectorComponents; - case LV_InvalidExpression: - // If the top level is a C-style cast, and the subexpression is a valid - // lvalue, then this is probably a use of the old-school "cast as lvalue" - // GCC extension. We don't support it, but we want to produce good - // diagnostics when it happens so that the user knows why. - if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(IgnoreParens())) { - if (CE->getSubExpr()->isLvalue(Ctx) == LV_Valid) { - if (Loc) - *Loc = CE->getLParenLoc(); - return MLV_LValueCast; - } - } - return MLV_InvalidExpression; - case LV_MemberFunction: return MLV_MemberFunction; - case LV_SubObjCPropertySetting: return MLV_SubObjCPropertySetting; - case LV_ClassTemporary: - return MLV_ClassTemporary; - } - - // The following is illegal: - // void takeclosure(void (^C)(void)); - // void func() { int x = 1; takeclosure(^{ x = 7; }); } - // - if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(this)) { - if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl())) - return MLV_NotBlockQualified; - } - - // Assigning to an 'implicit' property? - if (const ObjCImplicitSetterGetterRefExpr* Expr = - dyn_cast<ObjCImplicitSetterGetterRefExpr>(this)) { - if (Expr->getSetterMethod() == 0) - return MLV_NoSetterProperty; - } - - QualType CT = Ctx.getCanonicalType(getType()); - - if (CT.isConstQualified()) - return MLV_ConstQualified; - if (CT->isArrayType()) - return MLV_ArrayType; - if (CT->isIncompleteType()) - return MLV_IncompleteType; - - if (const RecordType *r = CT->getAs<RecordType>()) { - if (r->hasConstFields()) - return MLV_ConstQualified; - } - - return MLV_Valid; -} - /// isOBJCGCCandidate - Check if an expression is objc gc'able. /// returns true, if it is; false otherwise. bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { @@ -1596,7 +1253,7 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { if (CastExpr *P = dyn_cast<CastExpr>(E)) { // We ignore integer <-> casts that are of the same width, ptr<->ptr and - // ptr<->int casts of the same width. We also ignore all identify casts. + // ptr<->int casts of the same width. We also ignore all identity casts. Expr *SE = P->getSubExpr(); if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) { @@ -1604,8 +1261,10 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { continue; } - if ((E->getType()->isPointerType() || E->getType()->isIntegralType()) && - (SE->getType()->isPointerType() || SE->getType()->isIntegralType()) && + if ((E->getType()->isPointerType() || + E->getType()->isIntegralType(Ctx)) && + (SE->getType()->isPointerType() || + SE->getType()->isIntegralType(Ctx)) && Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) { E = SE; continue; @@ -1795,7 +1454,7 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx, // If the unthinkable happens, fall through to the safest alternative. case NPC_ValueDependentIsNull: - return isTypeDependent() || getType()->isIntegralType(); + return isTypeDependent() || getType()->isIntegralType(Ctx); case NPC_ValueDependentIsNotNull: return false; diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index d1a2b26..c2548ec 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -74,27 +74,27 @@ Stmt::child_iterator CXXDefaultArgExpr::child_end() { return child_iterator(); } -// CXXZeroInitValueExpr -Stmt::child_iterator CXXZeroInitValueExpr::child_begin() { +// CXXScalarValueInitExpr +Stmt::child_iterator CXXScalarValueInitExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator CXXZeroInitValueExpr::child_end() { +Stmt::child_iterator CXXScalarValueInitExpr::child_end() { return child_iterator(); } // CXXNewExpr CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs, unsigned numPlaceArgs, - bool parenTypeId, Expr *arraySize, + SourceRange TypeIdParens, Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, Expr **constructorArgs, unsigned numConsArgs, FunctionDecl *operatorDelete, QualType ty, SourceLocation startLoc, SourceLocation endLoc) : Expr(CXXNewExprClass, ty, ty->isDependentType(), ty->isDependentType()), - GlobalNew(globalNew), ParenTypeId(parenTypeId), + GlobalNew(globalNew), Initializer(initializer), SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), Constructor(constructor), - StartLoc(startLoc), EndLoc(endLoc) { + TypeIdParens(TypeIdParens), StartLoc(startLoc), EndLoc(endLoc) { AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs); unsigned i = 0; @@ -190,6 +190,18 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent, return ULE; } +UnresolvedLookupExpr * +UnresolvedLookupExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) { + std::size_t size = sizeof(UnresolvedLookupExpr); + if (NumTemplateArgs != 0) + size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + + void *Mem = C.Allocate(size, llvm::alignof<UnresolvedLookupExpr>()); + UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell()); + E->HasExplicitTemplateArgs = NumTemplateArgs != 0; + return E; +} + OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, @@ -197,19 +209,28 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T, UnresolvedSetIterator Begin, UnresolvedSetIterator End) : Expr(K, T, Dependent, Dependent), - Results(0), NumResults(End - Begin), Name(Name), Qualifier(Qualifier), + Results(0), NumResults(0), Name(Name), Qualifier(Qualifier), QualifierRange(QRange), NameLoc(NameLoc), HasExplicitTemplateArgs(HasTemplateArgs) { + initializeResults(C, Begin, End); +} + +void OverloadExpr::initializeResults(ASTContext &C, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + assert(Results == 0 && "Results already initialized!"); + NumResults = End - Begin; if (NumResults) { Results = static_cast<DeclAccessPair *>( C.Allocate(sizeof(DeclAccessPair) * NumResults, llvm::alignof<DeclAccessPair>())); memcpy(Results, &*Begin.getIterator(), - (End - Begin) * sizeof(DeclAccessPair)); + NumResults * sizeof(DeclAccessPair)); } } + bool OverloadExpr::ComputeDependence(UnresolvedSetIterator Begin, UnresolvedSetIterator End, const TemplateArgumentListInfo *Args) { @@ -269,6 +290,19 @@ DependentScopeDeclRefExpr::Create(ASTContext &C, return DRE; } +DependentScopeDeclRefExpr * +DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C, + unsigned NumTemplateArgs) { + std::size_t size = sizeof(DependentScopeDeclRefExpr); + if (NumTemplateArgs) + size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + void *Mem = C.Allocate(size); + + return new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(), + DeclarationName(),SourceLocation(), + NumTemplateArgs != 0); +} + StmtIterator DependentScopeDeclRefExpr::child_begin() { return child_iterator(); } @@ -535,14 +569,6 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, } } -CXXConstructExpr::CXXConstructExpr(EmptyShell Empty, ASTContext &C, - unsigned numargs) - : Expr(CXXConstructExprClass, Empty), Args(0), NumArgs(numargs) -{ - if (NumArgs) - Args = new (C) Stmt*[NumArgs]; -} - void CXXConstructExpr::DoDestroy(ASTContext &C) { DestroyChildren(C); if (Args) @@ -656,6 +682,14 @@ CXXUnresolvedConstructExpr::Create(ASTContext &C, Args, NumArgs, RParenLoc); } +CXXUnresolvedConstructExpr * +CXXUnresolvedConstructExpr::CreateEmpty(ASTContext &C, unsigned NumArgs) { + Stmt::EmptyShell Empty; + void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) + + sizeof(Expr *) * NumArgs); + return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs); +} + Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() { return child_iterator(reinterpret_cast<Stmt **>(this + 1)); } @@ -714,6 +748,29 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, Member, MemberLoc, TemplateArgs); } +CXXDependentScopeMemberExpr * +CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, + unsigned NumTemplateArgs) { + if (NumTemplateArgs == 0) + return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(), + 0, SourceLocation(), 0, + SourceRange(), 0, + DeclarationName(), + SourceLocation()); + + std::size_t size = sizeof(CXXDependentScopeMemberExpr) + + ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + void *Mem = C.Allocate(size, llvm::alignof<CXXDependentScopeMemberExpr>()); + CXXDependentScopeMemberExpr *E + = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(), + 0, SourceLocation(), 0, + SourceRange(), 0, + DeclarationName(), + SourceLocation(), 0); + E->HasExplicitTemplateArgs = true; + return E; +} + Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() { return child_iterator(&Base); } @@ -770,6 +827,18 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent, Member, MemberLoc, TemplateArgs, Begin, End); } +UnresolvedMemberExpr * +UnresolvedMemberExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) { + std::size_t size = sizeof(UnresolvedMemberExpr); + if (NumTemplateArgs != 0) + size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + + void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>()); + UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell()); + E->HasExplicitTemplateArgs = NumTemplateArgs != 0; + return E; +} + CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { // Unlike for UnresolvedLookupExpr, it is very easy to re-derive this. diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp new file mode 100644 index 0000000..60ac347 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -0,0 +1,471 @@ +//===--- ExprClassification.cpp - Expression AST Node Implementation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Expr::classify. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ErrorHandling.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +using namespace clang; + +typedef Expr::Classification Cl; + +static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E); +static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D); +static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T); +static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E); +static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E); +static Cl::Kinds ClassifyConditional(ASTContext &Ctx, + const ConditionalOperator *E); +static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, + Cl::Kinds Kind, SourceLocation &Loc); + +Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { + assert(!TR->isReferenceType() && "Expressions can't have reference type."); + + Cl::Kinds kind = ClassifyInternal(Ctx, this); + // C99 6.3.2.1: An lvalue is an expression with an object type or an + // incomplete type other than void. + if (!Ctx.getLangOptions().CPlusPlus) { + // Thus, no functions. + if (TR->isFunctionType() || TR == Ctx.OverloadTy) + kind = Cl::CL_Function; + // No void either, but qualified void is OK because it is "other than void". + else if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers()) + kind = Cl::CL_Void; + } + + Cl::ModifiableType modifiable = Cl::CM_Untested; + if (Loc) + modifiable = IsModifiable(Ctx, this, kind, *Loc); + return Classification(kind, modifiable); +} + +static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { + // This function takes the first stab at classifying expressions. + const LangOptions &Lang = Ctx.getLangOptions(); + + switch (E->getStmtClass()) { + // First come the expressions that are always lvalues, unconditionally. + + case Expr::ObjCIsaExprClass: + // C++ [expr.prim.general]p1: A string literal is an lvalue. + case Expr::StringLiteralClass: + // @encode is equivalent to its string + case Expr::ObjCEncodeExprClass: + // __func__ and friends are too. + case Expr::PredefinedExprClass: + // Property references are lvalues + case Expr::ObjCPropertyRefExprClass: + case Expr::ObjCImplicitSetterGetterRefExprClass: + // C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of... + case Expr::CXXTypeidExprClass: + // Unresolved lookups get classified as lvalues. + // FIXME: Is this wise? Should they get their own kind? + case Expr::UnresolvedLookupExprClass: + case Expr::UnresolvedMemberExprClass: + // ObjC instance variables are lvalues + // FIXME: ObjC++0x might have different rules + case Expr::ObjCIvarRefExprClass: + // C99 6.5.2.5p5 says that compound literals are lvalues. + // FIXME: C++ might have a different opinion. + case Expr::CompoundLiteralExprClass: + return Cl::CL_LValue; + + // Next come the complicated cases. + + // C++ [expr.sub]p1: The result is an lvalue of type "T". + // However, subscripting vector types is more like member access. + case Expr::ArraySubscriptExprClass: + if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType()) + return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase()); + return Cl::CL_LValue; + + // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a + // function or variable and a prvalue otherwise. + case Expr::DeclRefExprClass: + return ClassifyDecl(Ctx, cast<DeclRefExpr>(E)->getDecl()); + // We deal with names referenced from blocks the same way. + case Expr::BlockDeclRefExprClass: + return ClassifyDecl(Ctx, cast<BlockDeclRefExpr>(E)->getDecl()); + + // Member access is complex. + case Expr::MemberExprClass: + return ClassifyMemberExpr(Ctx, cast<MemberExpr>(E)); + + case Expr::UnaryOperatorClass: + switch (cast<UnaryOperator>(E)->getOpcode()) { + // C++ [expr.unary.op]p1: The unary * operator performs indirection: + // [...] the result is an lvalue referring to the object or function + // to which the expression points. + case UnaryOperator::Deref: + return Cl::CL_LValue; + + // GNU extensions, simply look through them. + case UnaryOperator::Real: + case UnaryOperator::Imag: + case UnaryOperator::Extension: + return ClassifyInternal(Ctx, cast<UnaryOperator>(E)->getSubExpr()); + + // C++ [expr.pre.incr]p1: The result is the updated operand; it is an + // lvalue, [...] + // Not so in C. + case UnaryOperator::PreInc: + case UnaryOperator::PreDec: + return Lang.CPlusPlus ? Cl::CL_LValue : Cl::CL_PRValue; + + default: + return Cl::CL_PRValue; + } + + // Implicit casts are lvalues if they're lvalue casts. Other than that, we + // only specifically record class temporaries. + case Expr::ImplicitCastExprClass: + if (cast<ImplicitCastExpr>(E)->isLvalueCast()) + return Cl::CL_LValue; + return Lang.CPlusPlus && E->getType()->isRecordType() ? + Cl::CL_ClassTemporary : Cl::CL_PRValue; + + // C++ [expr.prim.general]p4: The presence of parentheses does not affect + // whether the expression is an lvalue. + case Expr::ParenExprClass: + return ClassifyInternal(Ctx, cast<ParenExpr>(E)->getSubExpr()); + + case Expr::BinaryOperatorClass: + case Expr::CompoundAssignOperatorClass: + // C doesn't have any binary expressions that are lvalues. + if (Lang.CPlusPlus) + return ClassifyBinaryOp(Ctx, cast<BinaryOperator>(E)); + return Cl::CL_PRValue; + + case Expr::CallExprClass: + case Expr::CXXOperatorCallExprClass: + case Expr::CXXMemberCallExprClass: + return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType()); + + // __builtin_choose_expr is equivalent to the chosen expression. + case Expr::ChooseExprClass: + return ClassifyInternal(Ctx, cast<ChooseExpr>(E)->getChosenSubExpr(Ctx)); + + // Extended vector element access is an lvalue unless there are duplicates + // in the shuffle expression. + case Expr::ExtVectorElementExprClass: + return cast<ExtVectorElementExpr>(E)->containsDuplicateElements() ? + Cl::CL_DuplicateVectorComponents : Cl::CL_LValue; + + // Simply look at the actual default argument. + case Expr::CXXDefaultArgExprClass: + return ClassifyInternal(Ctx, cast<CXXDefaultArgExpr>(E)->getExpr()); + + // Same idea for temporary binding. + case Expr::CXXBindTemporaryExprClass: + return ClassifyInternal(Ctx, cast<CXXBindTemporaryExpr>(E)->getSubExpr()); + + // And the temporary lifetime guard. + case Expr::CXXExprWithTemporariesClass: + return ClassifyInternal(Ctx, cast<CXXExprWithTemporaries>(E)->getSubExpr()); + + // Casts depend completely on the target type. All casts work the same. + case Expr::CStyleCastExprClass: + case Expr::CXXFunctionalCastExprClass: + case Expr::CXXStaticCastExprClass: + case Expr::CXXDynamicCastExprClass: + case Expr::CXXReinterpretCastExprClass: + case Expr::CXXConstCastExprClass: + // 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::ConditionalOperatorClass: + // Once again, only C++ is interesting. + if (!Lang.CPlusPlus) return Cl::CL_PRValue; + return ClassifyConditional(Ctx, cast<ConditionalOperator>(E)); + + // ObjC message sends are effectively function calls, if the target function + // is known. + case Expr::ObjCMessageExprClass: + if (const ObjCMethodDecl *Method = + cast<ObjCMessageExpr>(E)->getMethodDecl()) { + return ClassifyUnnamed(Ctx, Method->getResultType()); + } + + // Some C++ expressions are always class temporaries. + case Expr::CXXConstructExprClass: + case Expr::CXXTemporaryObjectExprClass: + case Expr::CXXScalarValueInitExprClass: + return Cl::CL_ClassTemporary; + + // Everything we haven't handled is a prvalue. + default: + return Cl::CL_PRValue; + } +} + +/// ClassifyDecl - Return the classification of an expression referencing the +/// given declaration. +static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { + // C++ [expr.prim.general]p6: The result is an lvalue if the entity is a + // function, variable, or data member and a prvalue otherwise. + // In C, functions are not lvalues. + // In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an + // lvalue unless it's a reference type (C++ [temp.param]p6), so we need to + // special-case this. + bool islvalue; + if (const NonTypeTemplateParmDecl *NTTParm = + dyn_cast<NonTypeTemplateParmDecl>(D)) + islvalue = NTTParm->getType()->isReferenceType(); + else + islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || + (Ctx.getLangOptions().CPlusPlus && + (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D))); + + return islvalue ? Cl::CL_LValue : Cl::CL_PRValue; +} + +/// ClassifyUnnamed - Return the classification of an expression yielding an +/// unnamed value of the given type. This applies in particular to function +/// calls and casts. +static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) { + // In C, function calls are always rvalues. + if (!Ctx.getLangOptions().CPlusPlus) return Cl::CL_PRValue; + + // C++ [expr.call]p10: A function call is an lvalue if the result type is an + // lvalue reference type or an rvalue reference to function type, an xvalue + // if the result type is an rvalue refernence to object type, and a prvalue + // otherwise. + if (T->isLValueReferenceType()) + return Cl::CL_LValue; + const RValueReferenceType *RV = T->getAs<RValueReferenceType>(); + if (!RV) // Could still be a class temporary, though. + return T->isRecordType() ? Cl::CL_ClassTemporary : Cl::CL_PRValue; + + return RV->getPointeeType()->isFunctionType() ? Cl::CL_LValue : Cl::CL_XValue; +} + +static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { + // Handle C first, it's easier. + if (!Ctx.getLangOptions().CPlusPlus) { + // C99 6.5.2.3p3 + // For dot access, the expression is an lvalue if the first part is. For + // arrow access, it always is an lvalue. + if (E->isArrow()) + return Cl::CL_LValue; + // ObjC property accesses are not lvalues, but get special treatment. + Expr *Base = E->getBase(); + if (isa<ObjCPropertyRefExpr>(Base) || + isa<ObjCImplicitSetterGetterRefExpr>(Base)) + return Cl::CL_SubObjCPropertySetting; + return ClassifyInternal(Ctx, Base); + } + + NamedDecl *Member = E->getMemberDecl(); + // C++ [expr.ref]p3: E1->E2 is converted to the equivalent form (*(E1)).E2. + // C++ [expr.ref]p4: If E2 is declared to have type "reference to T", then + // E1.E2 is an lvalue. + if (ValueDecl *Value = dyn_cast<ValueDecl>(Member)) + if (Value->getType()->isReferenceType()) + return Cl::CL_LValue; + + // Otherwise, one of the following rules applies. + // -- If E2 is a static member [...] then E1.E2 is an lvalue. + if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord()) + return Cl::CL_LValue; + + // -- If E2 is a non-static data member [...]. If E1 is an lvalue, then + // E1.E2 is an lvalue; if E1 is an xvalue, then E1.E2 is an xvalue; + // otherwise, it is a prvalue. + if (isa<FieldDecl>(Member)) { + // *E1 is an lvalue + if (E->isArrow()) + return Cl::CL_LValue; + return ClassifyInternal(Ctx, E->getBase()); + } + + // -- If E2 is a [...] member function, [...] + // -- If it refers to a static member function [...], then E1.E2 is an + // lvalue; [...] + // -- Otherwise [...] E1.E2 is a prvalue. + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) + return Method->isStatic() ? Cl::CL_LValue : Cl::CL_MemberFunction; + + // -- If E2 is a member enumerator [...], the expression E1.E2 is a prvalue. + // So is everything else we haven't handled yet. + return Cl::CL_PRValue; +} + +static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { + assert(Ctx.getLangOptions().CPlusPlus && + "This is only relevant for C++."); + // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand. + if (E->isAssignmentOp()) + return Cl::CL_LValue; + + // C++ [expr.comma]p1: the result is of the same value category as its right + // operand, [...]. + if (E->getOpcode() == BinaryOperator::Comma) + return ClassifyInternal(Ctx, E->getRHS()); + + // C++ [expr.mptr.oper]p6: The result of a .* expression whose second operand + // is a pointer to a data member is of the same value category as its first + // operand. + if (E->getOpcode() == BinaryOperator::PtrMemD) + return E->getType()->isFunctionType() ? Cl::CL_MemberFunction : + ClassifyInternal(Ctx, E->getLHS()); + + // C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its + // second operand is a pointer to data member and a prvalue otherwise. + if (E->getOpcode() == BinaryOperator::PtrMemI) + return E->getType()->isFunctionType() ? + Cl::CL_MemberFunction : Cl::CL_LValue; + + // All other binary operations are prvalues. + return Cl::CL_PRValue; +} + +static Cl::Kinds ClassifyConditional(ASTContext &Ctx, + const ConditionalOperator *E) { + assert(Ctx.getLangOptions().CPlusPlus && + "This is only relevant for C++."); + + Expr *True = E->getTrueExpr(); + Expr *False = E->getFalseExpr(); + // C++ [expr.cond]p2 + // If either the second or the third operand has type (cv) void, [...] + // the result [...] is a prvalue. + if (True->getType()->isVoidType() || False->getType()->isVoidType()) + return Cl::CL_PRValue; + + // Note that at this point, we have already performed all conversions + // according to [expr.cond]p3. + // C++ [expr.cond]p4: If the second and third operands are glvalues of the + // same value category [...], the result is of that [...] value category. + // C++ [expr.cond]p5: Otherwise, the result is a prvalue. + Cl::Kinds LCl = ClassifyInternal(Ctx, True), + RCl = ClassifyInternal(Ctx, False); + return LCl == RCl ? LCl : Cl::CL_PRValue; +} + +static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, + Cl::Kinds Kind, SourceLocation &Loc) { + // As a general rule, we only care about lvalues. But there are some rvalues + // for which we want to generate special results. + if (Kind == Cl::CL_PRValue) { + // For the sake of better diagnostics, we want to specifically recognize + // use of the GCC cast-as-lvalue extension. + if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E->IgnoreParens())){ + if (CE->getSubExpr()->Classify(Ctx).isLValue()) { + Loc = CE->getLParenLoc(); + return Cl::CM_LValueCast; + } + } + } + if (Kind != Cl::CL_LValue) + return Cl::CM_RValue; + + // This is the lvalue case. + // Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6) + if (Ctx.getLangOptions().CPlusPlus && E->getType()->isFunctionType()) + return Cl::CM_Function; + + // You cannot assign to a variable outside a block from within the block if + // it is not marked __block, e.g. + // void takeclosure(void (^C)(void)); + // void func() { int x = 1; takeclosure(^{ x = 7; }); } + if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E)) { + if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl())) + return Cl::CM_NotBlockQualified; + } + + // Assignment to a property in ObjC is an implicit setter access. But a + // setter might not exist. + if (const ObjCImplicitSetterGetterRefExpr *Expr = + dyn_cast<ObjCImplicitSetterGetterRefExpr>(E)) { + if (Expr->getSetterMethod() == 0) + return Cl::CM_NoSetterProperty; + } + + CanQualType CT = Ctx.getCanonicalType(E->getType()); + // Const stuff is obviously not modifiable. + if (CT.isConstQualified()) + return Cl::CM_ConstQualified; + // Arrays are not modifiable, only their elements are. + if (CT->isArrayType()) + return Cl::CM_ArrayType; + // Incomplete types are not modifiable. + if (CT->isIncompleteType()) + return Cl::CM_IncompleteType; + + // Records with any const fields (recursively) are not modifiable. + if (const RecordType *R = CT->getAs<RecordType>()) { + assert(!Ctx.getLangOptions().CPlusPlus && + "C++ struct assignment should be resolved by the " + "copy assignment operator."); + if (R->hasConstFields()) + return Cl::CM_ConstQualified; + } + + return Cl::CM_Modifiable; +} + +Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { + Classification VC = Classify(Ctx); + switch (VC.getKind()) { + case Cl::CL_LValue: return LV_Valid; + case Cl::CL_XValue: return LV_InvalidExpression; + case Cl::CL_Function: return LV_NotObjectType; + case Cl::CL_Void: return LV_IncompleteVoidType; + case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents; + case Cl::CL_MemberFunction: return LV_MemberFunction; + case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting; + case Cl::CL_ClassTemporary: return LV_ClassTemporary; + case Cl::CL_PRValue: return LV_InvalidExpression; + } + llvm_unreachable("Unhandled kind"); +} + +Expr::isModifiableLvalueResult +Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { + SourceLocation dummy; + Classification VC = ClassifyModifiable(Ctx, Loc ? *Loc : dummy); + switch (VC.getKind()) { + case Cl::CL_LValue: break; + case Cl::CL_XValue: return MLV_InvalidExpression; + case Cl::CL_Function: return MLV_NotObjectType; + case Cl::CL_Void: return MLV_IncompleteVoidType; + case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents; + case Cl::CL_MemberFunction: return MLV_MemberFunction; + case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting; + case Cl::CL_ClassTemporary: return MLV_ClassTemporary; + case Cl::CL_PRValue: + return VC.getModifiable() == Cl::CM_LValueCast ? + MLV_LValueCast : MLV_InvalidExpression; + } + assert(VC.getKind() == Cl::CL_LValue && "Unhandled kind"); + switch (VC.getModifiable()) { + case Cl::CM_Untested: llvm_unreachable("Did not test modifiability"); + case Cl::CM_Modifiable: return MLV_Valid; + case Cl::CM_RValue: llvm_unreachable("CM_RValue and CL_LValue don't match"); + case Cl::CM_Function: return MLV_NotObjectType; + case Cl::CM_LValueCast: + llvm_unreachable("CM_LValueCast and CL_LValue don't match"); + case Cl::CM_NotBlockQualified: return MLV_NotBlockQualified; + case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty; + case Cl::CM_ConstQualified: return MLV_ConstQualified; + case Cl::CM_ArrayType: return MLV_ArrayType; + case Cl::CM_IncompleteType: return MLV_IncompleteType; + } + llvm_unreachable("Unhandled modifiable type"); +} diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index dc61401..3c97420 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -157,7 +157,7 @@ static bool EvalPointerValueAsBool(LValue& Value, bool& Result) { static bool HandleConversionToBool(const Expr* E, bool& Result, EvalInfo &Info) { - if (E->getType()->isIntegralType()) { + if (E->getType()->isIntegralOrEnumerationType()) { APSInt IntResult; if (!EvaluateInteger(E, IntResult, Info)) return false; @@ -542,7 +542,7 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { SubExpr->getType()->isBlockPointerType()) return Visit(SubExpr); - if (SubExpr->getType()->isIntegralType()) { + if (SubExpr->getType()->isIntegralOrEnumerationType()) { APValue Value; if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) break; @@ -563,6 +563,7 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { case CastExpr::CK_NoOp: case CastExpr::CK_BitCast: + case CastExpr::CK_LValueBitCast: case CastExpr::CK_AnyPointerToObjCPointerCast: case CastExpr::CK_AnyPointerToBlockPointerCast: return Visit(SubExpr); @@ -746,25 +747,46 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { QualType EltTy = VT->getElementType(); llvm::SmallVector<APValue, 4> Elements; - for (unsigned i = 0; i < NumElements; i++) { + // If a vector is initialized with a single element, that value + // becomes every element of the vector, not just the first. + // This is the behavior described in the IBM AltiVec documentation. + if (NumInits == 1) { + APValue InitValue; if (EltTy->isIntegerType()) { llvm::APSInt sInt(32); - if (i < NumInits) { - if (!EvaluateInteger(E->getInit(i), sInt, Info)) - return APValue(); - } else { - sInt = Info.Ctx.MakeIntValue(0, EltTy); - } - Elements.push_back(APValue(sInt)); + if (!EvaluateInteger(E->getInit(0), sInt, Info)) + return APValue(); + InitValue = APValue(sInt); } else { llvm::APFloat f(0.0); - if (i < NumInits) { - if (!EvaluateFloat(E->getInit(i), f, Info)) - return APValue(); + if (!EvaluateFloat(E->getInit(0), f, Info)) + return APValue(); + InitValue = APValue(f); + } + for (unsigned i = 0; i < NumElements; i++) { + Elements.push_back(InitValue); + } + } else { + for (unsigned i = 0; i < NumElements; i++) { + if (EltTy->isIntegerType()) { + llvm::APSInt sInt(32); + if (i < NumInits) { + if (!EvaluateInteger(E->getInit(i), sInt, Info)) + return APValue(); + } else { + sInt = Info.Ctx.MakeIntValue(0, EltTy); + } + Elements.push_back(APValue(sInt)); } else { - f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); + llvm::APFloat f(0.0); + if (i < NumInits) { + if (!EvaluateFloat(E->getInit(i), f, Info)) + return APValue(); + } else { + f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); + } + Elements.push_back(APValue(f)); } - Elements.push_back(APValue(f)); } } return APValue(&Elements[0], Elements.size()); @@ -818,7 +840,8 @@ public: : Info(info), Result(result) {} bool Success(const llvm::APSInt &SI, const Expr *E) { - assert(E->getType()->isIntegralType() && "Invalid evaluation result."); + assert(E->getType()->isIntegralOrEnumerationType() && + "Invalid evaluation result."); assert(SI.isSigned() == E->getType()->isSignedIntegerType() && "Invalid evaluation result."); assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && @@ -828,7 +851,8 @@ public: } bool Success(const llvm::APInt &I, const Expr *E) { - assert(E->getType()->isIntegralType() && "Invalid evaluation result."); + assert(E->getType()->isIntegralOrEnumerationType() && + "Invalid evaluation result."); assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(APSInt(I)); @@ -837,7 +861,8 @@ public: } bool Success(uint64_t Value, const Expr *E) { - assert(E->getType()->isIntegralType() && "Invalid evaluation result."); + assert(E->getType()->isIntegralOrEnumerationType() && + "Invalid evaluation result."); Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType())); return true; } @@ -914,7 +939,7 @@ public: return Success(0, E); } - bool VisitCXXZeroInitValueExpr(const CXXZeroInitValueExpr *E) { + bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { return Success(0, E); } @@ -943,12 +968,12 @@ private: } // end anonymous namespace static bool EvaluateIntegerOrLValue(const Expr* E, APValue &Result, EvalInfo &Info) { - assert(E->getType()->isIntegralType()); + assert(E->getType()->isIntegralOrEnumerationType()); return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); } static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) { - assert(E->getType()->isIntegralType()); + assert(E->getType()->isIntegralOrEnumerationType()); APValue Val; if (!EvaluateIntegerOrLValue(E, Val, Info) || !Val.isInt()) @@ -1314,8 +1339,8 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { return Success(Result, E); } } - if (!LHSTy->isIntegralType() || - !RHSTy->isIntegralType()) { + if (!LHSTy->isIntegralOrEnumerationType() || + !RHSTy->isIntegralOrEnumerationType()) { // We can't continue from here for non-integral types, and they // could potentially confuse the following operations. return false; @@ -1570,7 +1595,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { } // Only handle integral operations... - if (!E->getSubExpr()->getType()->isIntegralType()) + if (!E->getSubExpr()->getType()->isIntegralOrEnumerationType()) return false; // Get the operand value into 'Result'. @@ -1613,7 +1638,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { } // Handle simple integer->integer casts. - if (SrcType->isIntegralType()) { + if (SrcType->isIntegralOrEnumerationType()) { if (!Visit(SubExpr)) return false; @@ -1732,7 +1757,7 @@ public: bool VisitBinaryOperator(const BinaryOperator *E); bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitCastExpr(CastExpr *E); - bool VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E); + bool VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); bool VisitConditionalOperator(ConditionalOperator *E); bool VisitChooseExpr(const ChooseExpr *E) @@ -1908,7 +1933,7 @@ bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) { Expr* SubExpr = E->getSubExpr(); - if (SubExpr->getType()->isIntegralType()) { + if (SubExpr->getType()->isIntegralOrEnumerationType()) { APSInt IntResult; if (!EvaluateInteger(SubExpr, IntResult, Info)) return false; @@ -1928,7 +1953,7 @@ bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) { return false; } -bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { +bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); return true; } @@ -2186,6 +2211,8 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const { } else if (E->getType()->isIntegerType()) { if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(const_cast<Expr*>(E))) return false; + if (Result.Val.isLValue() && !IsGlobalLValue(Result.Val.getLValueBase())) + return false; } else if (E->getType()->hasPointerRepresentation()) { LValue LV; if (!EvaluatePointer(E, LV, Info)) @@ -2316,7 +2343,7 @@ static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) { static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); - if (!E->getType()->isIntegralType()) { + if (!E->getType()->isIntegralOrEnumerationType()) { return ICEDiag(2, E->getLocStart()); } @@ -2384,7 +2411,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::IntegerLiteralClass: case Expr::CharacterLiteralClass: case Expr::CXXBoolLiteralExprClass: - case Expr::CXXZeroInitValueExprClass: + case Expr::CXXScalarValueInitExprClass: case Expr::TypesCompatibleExprClass: case Expr::UnaryTypeTraitExprClass: return NoDiag(); @@ -2579,7 +2606,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXReinterpretCastExprClass: case Expr::CXXConstCastExprClass: { const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr(); - if (SubExpr->getType()->isIntegralType()) + if (SubExpr->getType()->isIntegralOrEnumerationType()) return CheckICE(SubExpr, Ctx); if (isa<FloatingLiteral>(SubExpr->IgnoreParens())) return NoDiag(); diff --git a/contrib/llvm/tools/clang/lib/AST/Makefile b/contrib/llvm/tools/clang/lib/AST/Makefile index ede2577..7a1672b 100644 --- a/contrib/llvm/tools/clang/lib/AST/Makefile +++ b/contrib/llvm/tools/clang/lib/AST/Makefile @@ -11,11 +11,9 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../../../.. +CLANG_LEVEL := ../.. LIBRARYNAME := clangAST BUILD_ARCHIVE = 1 -CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include - -include $(LEVEL)/Makefile.common +include $(CLANG_LEVEL)/Makefile diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index 983a287..88d71ce 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -23,6 +23,35 @@ using namespace clang; namespace { +/// BaseSubobjectInfo - Represents a single base subobject in a complete class. +/// For a class hierarchy like +/// +/// class A { }; +/// class B : A { }; +/// class C : A, B { }; +/// +/// The BaseSubobjectInfo graph for C will have three BaseSubobjectInfo +/// instances, one for B and two for A. +/// +/// If a base is virtual, it will only have one BaseSubobjectInfo allocated. +struct BaseSubobjectInfo { + /// Class - The class for this base info. + const CXXRecordDecl *Class; + + /// IsVirtual - Whether the BaseInfo represents a virtual base or not. + bool IsVirtual; + + /// Bases - Information about the base subobjects. + llvm::SmallVector<BaseSubobjectInfo*, 4> Bases; + + /// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base + /// of this base info (if one exists). + BaseSubobjectInfo *PrimaryVirtualBaseInfo; + + // FIXME: Document. + const BaseSubobjectInfo *Derived; +}; + /// EmptySubobjectMap - Keeps track of which empty subobjects exist at different /// offsets while laying out a C++ class. class EmptySubobjectMap { @@ -36,30 +65,41 @@ class EmptySubobjectMap { typedef llvm::DenseMap<uint64_t, ClassVectorTy> EmptyClassOffsetsMapTy; EmptyClassOffsetsMapTy EmptyClassOffsets; + /// MaxEmptyClassOffset - The highest offset known to contain an empty + /// base subobject. + uint64_t MaxEmptyClassOffset; + /// ComputeEmptySubobjectSizes - Compute the size of the largest base or /// member subobject that is empty. void ComputeEmptySubobjectSizes(); + + bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD, + uint64_t Offset) const; - struct BaseInfo { - const CXXRecordDecl *Class; - bool IsVirtual; - - const CXXRecordDecl *PrimaryVirtualBase; - - llvm::SmallVector<BaseInfo*, 4> Bases; - const BaseInfo *Derived; - }; + void AddSubobjectAtOffset(const CXXRecordDecl *RD, uint64_t Offset); - llvm::DenseMap<const CXXRecordDecl *, BaseInfo *> VirtualBaseInfo; - llvm::DenseMap<const CXXRecordDecl *, BaseInfo *> NonVirtualBaseInfo; + bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info, + uint64_t Offset); + void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info, + uint64_t Offset, bool PlacingEmptyBase); - BaseInfo *ComputeBaseInfo(const CXXRecordDecl *RD, bool IsVirtual, - const BaseInfo *Derived); - void ComputeBaseInfo(); + bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD, + const CXXRecordDecl *Class, + uint64_t Offset) const; + bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD, + uint64_t Offset) const; - bool CanPlaceBaseSubobjectAtOffset(const BaseInfo *Info, uint64_t Offset); - void UpdateEmptyBaseSubobjects(const BaseInfo *Info, uint64_t Offset); + void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD, + const CXXRecordDecl *Class, + uint64_t Offset); + void UpdateEmptyFieldSubobjects(const FieldDecl *FD, uint64_t Offset); + /// AnyEmptySubobjectsBeyondOffset - Returns whether there are any empty + /// subobjects beyond the given offset. + bool AnyEmptySubobjectsBeyondOffset(uint64_t Offset) const { + return Offset <= MaxEmptyClassOffset; + } + public: /// This holds the size of the largest empty subobject (either a base /// or a member). Will be zero if the record being built doesn't contain @@ -67,18 +107,21 @@ public: uint64_t SizeOfLargestEmptySubobject; EmptySubobjectMap(ASTContext &Context, const CXXRecordDecl *Class) - : Context(Context), Class(Class), SizeOfLargestEmptySubobject(0) { + : Context(Context), Class(Class), MaxEmptyClassOffset(0), + SizeOfLargestEmptySubobject(0) { ComputeEmptySubobjectSizes(); - - ComputeBaseInfo(); } /// CanPlaceBaseAtOffset - Return whether the given base class can be placed /// at the given offset. /// Returns false if placing the record will result in two components /// (direct or indirect) of the same type having the same offset. - bool CanPlaceBaseAtOffset(const CXXRecordDecl *RD, bool BaseIsVirtual, + bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info, uint64_t Offset); + + /// CanPlaceFieldAtOffset - Return whether a field can be placed at the given + /// offset. + bool CanPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset); }; void EmptySubobjectMap::ComputeEmptySubobjectSizes() { @@ -130,93 +173,67 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() { } } -EmptySubobjectMap::BaseInfo * -EmptySubobjectMap::ComputeBaseInfo(const CXXRecordDecl *RD, bool IsVirtual, - const BaseInfo *Derived) { - BaseInfo *Info; - - if (IsVirtual) { - BaseInfo *&InfoSlot = VirtualBaseInfo[RD]; - if (InfoSlot) { - assert(InfoSlot->Class == RD && "Wrong class for virtual base info!"); - return InfoSlot; - } +bool +EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD, + uint64_t Offset) const { + // We only need to check empty bases. + if (!RD->isEmpty()) + return true; - InfoSlot = new (Context) BaseInfo; - Info = InfoSlot; - } else { - Info = new (Context) BaseInfo; - } - - Info->Class = RD; - Info->IsVirtual = IsVirtual; - Info->Derived = Derived; - Info->PrimaryVirtualBase = 0; + EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset); + if (I == EmptyClassOffsets.end()) + return true; - if (RD->getNumVBases()) { - // Check if this class has a primary virtual base. - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - if (Layout.getPrimaryBaseWasVirtual()) { - Info->PrimaryVirtualBase = Layout.getPrimaryBase(); - assert(Info->PrimaryVirtualBase && - "Didn't have a primary virtual base!"); - } - } + const ClassVectorTy& Classes = I->second; + if (std::find(Classes.begin(), Classes.end(), RD) == Classes.end()) + return true; - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - bool IsVirtual = I->isVirtual(); - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - Info->Bases.push_back(ComputeBaseInfo(BaseDecl, IsVirtual, Info)); - } - - return Info; + // There is already an empty class of the same type at this offset. + return false; } + +void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD, + uint64_t Offset) { + // We only care about empty bases. + if (!RD->isEmpty()) + return; -void EmptySubobjectMap::ComputeBaseInfo() { - for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(), - E = Class->bases_end(); I != E; ++I) { - bool IsVirtual = I->isVirtual(); - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - BaseInfo *Info = ComputeBaseInfo(BaseDecl, IsVirtual, /*Derived=*/0); - if (IsVirtual) { - // ComputeBaseInfo has already added this base for us. - continue; - } + ClassVectorTy& Classes = EmptyClassOffsets[Offset]; + assert(std::find(Classes.begin(), Classes.end(), RD) == Classes.end() && + "Duplicate empty class detected!"); - // Add the base info to the map of non-virtual bases. - assert(!NonVirtualBaseInfo.count(BaseDecl) && - "Non-virtual base already exists!"); - NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info)); - } + Classes.push_back(RD); + + // Update the empty class offset. + MaxEmptyClassOffset = std::max(MaxEmptyClassOffset, Offset); } bool -EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseInfo *Info, +EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info, uint64_t Offset) { + // We don't have to keep looking past the maximum offset that's known to + // contain an empty class. + if (!AnyEmptySubobjectsBeyondOffset(Offset)) + return true; + + if (!CanPlaceSubobjectAtOffset(Info->Class, Offset)) + return false; + // Traverse all non-virtual bases. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) { - BaseInfo* Base = Info->Bases[I]; + BaseSubobjectInfo* Base = Info->Bases[I]; if (Base->IsVirtual) continue; - const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class); if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset)) return false; } - if (Info->PrimaryVirtualBase) { - BaseInfo *PrimaryVirtualBaseInfo = - VirtualBaseInfo.lookup(Info->PrimaryVirtualBase); - assert(PrimaryVirtualBaseInfo && "Didn't find base info!"); + if (Info->PrimaryVirtualBaseInfo) { + BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo; if (Info == PrimaryVirtualBaseInfo->Derived) { if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset)) @@ -224,62 +241,277 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseInfo *Info, } } - // FIXME: Member variables. + // Traverse all member variables. + unsigned FieldNo = 0; + for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(), + E = Info->Class->field_end(); I != E; ++I, ++FieldNo) { + const FieldDecl *FD = *I; + + uint64_t FieldOffset = Offset + Layout.getFieldOffset(FieldNo); + if (!CanPlaceFieldSubobjectAtOffset(FD, FieldOffset)) + return false; + } + return true; } -void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseInfo *Info, - uint64_t Offset) { - if (Info->Class->isEmpty()) { - // FIXME: Record that there is an empty class at this offset. +void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info, + uint64_t Offset, + bool PlacingEmptyBase) { + if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) { + // We know that the only empty subobjects that can conflict with empty + // subobject of non-empty bases, are empty bases that can be placed at + // offset zero. Because of this, we only need to keep track of empty base + // subobjects with offsets less than the size of the largest empty + // subobject for our class. + return; } - + + AddSubobjectAtOffset(Info->Class, Offset); + // Traverse all non-virtual bases. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) { - BaseInfo* Base = Info->Bases[I]; + BaseSubobjectInfo* Base = Info->Bases[I]; if (Base->IsVirtual) continue; - - const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); + uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class); - - UpdateEmptyBaseSubobjects(Base, BaseOffset); + UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase); } - if (Info->PrimaryVirtualBase) { - BaseInfo *PrimaryVirtualBaseInfo = - VirtualBaseInfo.lookup(Info->PrimaryVirtualBase); - assert(PrimaryVirtualBaseInfo && "Didn't find base info!"); + if (Info->PrimaryVirtualBaseInfo) { + BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo; if (Info == PrimaryVirtualBaseInfo->Derived) - UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset); + UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset, + PlacingEmptyBase); + } + + // Traverse all member variables. + unsigned FieldNo = 0; + for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(), + E = Info->Class->field_end(); I != E; ++I, ++FieldNo) { + const FieldDecl *FD = *I; + + uint64_t FieldOffset = Offset + Layout.getFieldOffset(FieldNo); + UpdateEmptyFieldSubobjects(FD, FieldOffset); } - - // FIXME: Member variables. } -bool EmptySubobjectMap::CanPlaceBaseAtOffset(const CXXRecordDecl *RD, - bool BaseIsVirtual, +bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info, uint64_t Offset) { // If we know this class doesn't have any empty subobjects we don't need to // bother checking. if (!SizeOfLargestEmptySubobject) return true; - BaseInfo *Info; + if (!CanPlaceBaseSubobjectAtOffset(Info, Offset)) + return false; + + // We are able to place the base at this offset. Make sure to update the + // empty base subobject map. + UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty()); + return true; +} + +bool +EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD, + const CXXRecordDecl *Class, + uint64_t Offset) const { + // We don't have to keep looking past the maximum offset that's known to + // contain an empty class. + if (!AnyEmptySubobjectsBeyondOffset(Offset)) + return true; + + if (!CanPlaceSubobjectAtOffset(RD, Offset)) + return false; - if (BaseIsVirtual) - Info = VirtualBaseInfo.lookup(RD); - else - Info = NonVirtualBaseInfo.lookup(RD); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + // Traverse all non-virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + if (I->isVirtual()) + continue; + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl); + if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset)) + return false; + } + + if (RD == Class) { + // This is the most derived class, traverse virtual bases as well. + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), + E = RD->vbases_end(); I != E; ++I) { + const CXXRecordDecl *VBaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl); + if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset)) + return false; + } + } + + // Traverse all member variables. + unsigned FieldNo = 0; + for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I, ++FieldNo) { + const FieldDecl *FD = *I; + + uint64_t FieldOffset = Offset + Layout.getFieldOffset(FieldNo); + + if (!CanPlaceFieldSubobjectAtOffset(FD, FieldOffset)) + return false; + } + + return true; +} + +bool EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD, + uint64_t Offset) const { + // We don't have to keep looking past the maximum offset that's known to + // contain an empty class. + if (!AnyEmptySubobjectsBeyondOffset(Offset)) + return true; - if (!CanPlaceBaseSubobjectAtOffset(Info, Offset)) + QualType T = FD->getType(); + if (const RecordType *RT = T->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset); + } + + // If we have an array type we need to look at every element. + if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) { + QualType ElemTy = Context.getBaseElementType(AT); + const RecordType *RT = ElemTy->getAs<RecordType>(); + if (!RT) + return true; + + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + uint64_t NumElements = Context.getConstantArrayElementCount(AT); + uint64_t ElementOffset = Offset; + for (uint64_t I = 0; I != NumElements; ++I) { + // We don't have to keep looking past the maximum offset that's known to + // contain an empty class. + if (!AnyEmptySubobjectsBeyondOffset(ElementOffset)) + return true; + + if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset)) + return false; + + ElementOffset += Layout.getSize(); + } + } + + return true; +} + +bool +EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) { + if (!CanPlaceFieldSubobjectAtOffset(FD, Offset)) return false; - UpdateEmptyBaseSubobjects(Info, Offset); + // We are able to place the member variable at this offset. + // Make sure to update the empty base subobject map. + UpdateEmptyFieldSubobjects(FD, Offset); return true; } +void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD, + const CXXRecordDecl *Class, + uint64_t Offset) { + // We know that the only empty subobjects that can conflict with empty + // field subobjects are subobjects of empty bases that can be placed at offset + // zero. Because of this, we only need to keep track of empty field + // subobjects with offsets less than the size of the largest empty + // subobject for our class. + if (Offset >= SizeOfLargestEmptySubobject) + return; + + AddSubobjectAtOffset(RD, Offset); + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + // Traverse all non-virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + if (I->isVirtual()) + continue; + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl); + UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset); + } + + if (RD == Class) { + // This is the most derived class, traverse virtual bases as well. + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), + E = RD->vbases_end(); I != E; ++I) { + const CXXRecordDecl *VBaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl); + UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset); + } + } + + // Traverse all member variables. + unsigned FieldNo = 0; + for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I, ++FieldNo) { + const FieldDecl *FD = *I; + + uint64_t FieldOffset = Offset + Layout.getFieldOffset(FieldNo); + + UpdateEmptyFieldSubobjects(FD, FieldOffset); + } +} + +void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD, + uint64_t Offset) { + QualType T = FD->getType(); + if (const RecordType *RT = T->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + UpdateEmptyFieldSubobjects(RD, RD, Offset); + return; + } + + // If we have an array type we need to update every element. + if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) { + QualType ElemTy = Context.getBaseElementType(AT); + const RecordType *RT = ElemTy->getAs<RecordType>(); + if (!RT) + return; + + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + uint64_t NumElements = Context.getConstantArrayElementCount(AT); + uint64_t ElementOffset = Offset; + + for (uint64_t I = 0; I != NumElements; ++I) { + // We know that the only empty subobjects that can conflict with empty + // field subobjects are subobjects of empty bases that can be placed at + // offset zero. Because of this, we only need to keep track of empty field + // subobjects with offsets less than the size of the largest empty + // subobject for our class. + if (ElementOffset >= SizeOfLargestEmptySubobject) + return; + + UpdateEmptyFieldSubobjects(RD, RD, ElementOffset); + ElementOffset += Layout.getSize(); + } + } +} + class RecordLayoutBuilder { // FIXME: Remove this and make the appropriate fields public. friend class clang::ASTContext; @@ -346,10 +578,6 @@ class RecordLayoutBuilder { /// avoid visiting virtual bases more than once. llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases; - /// EmptyClassOffsets - A map from offsets to empty record decls. - typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy; - EmptyClassOffsetsTy EmptyClassOffsets; - RecordLayoutBuilder(ASTContext &Context, EmptySubobjectMap *EmptySubobjects) : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(8), Packed(false), IsUnion(false), IsMac68kAlign(false), @@ -366,9 +594,29 @@ class RecordLayoutBuilder { void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize); void LayoutBitField(const FieldDecl *D); - /// ComputeEmptySubobjectSizes - Compute the size of the largest base or - /// member subobject that is empty. - void ComputeEmptySubobjectSizes(const CXXRecordDecl *RD); + /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects. + llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator; + + typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *> + BaseSubobjectInfoMapTy; + + /// VirtualBaseInfo - Map from all the (direct or indirect) virtual bases + /// of the class we're laying out to their base subobject info. + BaseSubobjectInfoMapTy VirtualBaseInfo; + + /// NonVirtualBaseInfo - Map from all the direct non-virtual bases of the + /// class we're laying out to their base subobject info. + BaseSubobjectInfoMapTy NonVirtualBaseInfo; + + /// ComputeBaseSubobjectInfo - Compute the base subobject information for the + /// bases of the given class. + void ComputeBaseSubobjectInfo(const CXXRecordDecl *RD); + + /// ComputeBaseSubobjectInfo - Compute the base subobject information for a + /// single class and all of its base classes. + BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD, + bool IsVirtual, + BaseSubobjectInfo *Derived); /// DeterminePrimaryBase - Determine the primary base of the given class. void DeterminePrimaryBase(const CXXRecordDecl *RD); @@ -387,43 +635,21 @@ class RecordLayoutBuilder { void LayoutNonVirtualBases(const CXXRecordDecl *RD); /// LayoutNonVirtualBase - Lays out a single non-virtual base. - void LayoutNonVirtualBase(const CXXRecordDecl *Base); + void LayoutNonVirtualBase(const BaseSubobjectInfo *Base); - void AddPrimaryVirtualBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset, - const CXXRecordDecl *MostDerivedClass); + void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, + uint64_t Offset); /// LayoutVirtualBases - Lays out all the virtual bases. void LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass); /// LayoutVirtualBase - Lays out a single virtual base. - void LayoutVirtualBase(const CXXRecordDecl *Base); + void LayoutVirtualBase(const BaseSubobjectInfo *Base); /// LayoutBase - Will lay out a base and return the offset where it was /// placed, in bits. - uint64_t LayoutBase(const CXXRecordDecl *Base, bool BaseIsVirtual); - - /// canPlaceRecordAtOffset - Return whether a record (either a base class - /// or a field) can be placed at the given offset. - /// Returns false if placing the record will result in two components - /// (direct or indirect) of the same type having the same offset. - bool canPlaceRecordAtOffset(const CXXRecordDecl *RD, uint64_t Offset, - bool CheckVBases) const; - - /// canPlaceFieldAtOffset - Return whether a field can be placed at the given - /// offset. - bool canPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) const; - - /// UpdateEmptyClassOffsets - Called after a record (either a base class - /// or a field) has been placed at the given offset. Will update the - /// EmptyClassOffsets map if the class is empty or has any empty bases or - /// fields. - void UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset, - bool UpdateVBases); - - /// UpdateEmptyClassOffsets - Called after a field has been placed at the - /// given offset. - void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset); + uint64_t LayoutBase(const BaseSubobjectInfo *Base); /// InitializeLayout - Initialize record layout for the given record decl. void InitializeLayout(const Decl *D); @@ -575,14 +801,127 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { UpdateAlignment(Context.Target.getPointerAlign(0)); } +BaseSubobjectInfo * +RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD, + bool IsVirtual, + BaseSubobjectInfo *Derived) { + BaseSubobjectInfo *Info; + + if (IsVirtual) { + // Check if we already have info about this virtual base. + BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD]; + if (InfoSlot) { + assert(InfoSlot->Class == RD && "Wrong class for virtual base info!"); + return InfoSlot; + } + + // We don't, create it. + InfoSlot = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo; + Info = InfoSlot; + } else { + Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo; + } + + Info->Class = RD; + Info->IsVirtual = IsVirtual; + Info->Derived = 0; + Info->PrimaryVirtualBaseInfo = 0; + + const CXXRecordDecl *PrimaryVirtualBase = 0; + BaseSubobjectInfo *PrimaryVirtualBaseInfo = 0; + + // Check if this base has a primary virtual base. + if (RD->getNumVBases()) { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + if (Layout.getPrimaryBaseWasVirtual()) { + // This base does have a primary virtual base. + PrimaryVirtualBase = Layout.getPrimaryBase(); + assert(PrimaryVirtualBase && "Didn't have a primary virtual base!"); + + // Now check if we have base subobject info about this primary base. + PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase); + + if (PrimaryVirtualBaseInfo) { + if (PrimaryVirtualBaseInfo->Derived) { + // We did have info about this primary base, and it turns out that it + // has already been claimed as a primary virtual base for another + // base. + PrimaryVirtualBase = 0; + } else { + // We can claim this base as our primary base. + Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo; + PrimaryVirtualBaseInfo->Derived = Info; + } + } + } + } + + // Now go through all direct bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + bool IsVirtual = I->isVirtual(); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info)); + } + + if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) { + // Traversing the bases must have created the base info for our primary + // virtual base. + PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase); + assert(PrimaryVirtualBaseInfo && + "Did not create a primary virtual base!"); + + // Claim the primary virtual base as our primary virtual base. + Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo; + PrimaryVirtualBaseInfo->Derived = Info; + } + + return Info; +} + +void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) { + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + bool IsVirtual = I->isVirtual(); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Compute the base subobject info for this base. + BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, 0); + + if (IsVirtual) { + // ComputeBaseInfo has already added this base for us. + assert(VirtualBaseInfo.count(BaseDecl) && + "Did not add virtual base!"); + } else { + // Add the base info to the map of non-virtual bases. + assert(!NonVirtualBaseInfo.count(BaseDecl) && + "Non-virtual base already exists!"); + NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info)); + } + } +} + void RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { - // First, determine the primary base class. + // Then, determine the primary base class. DeterminePrimaryBase(RD); + // Compute base subobject info. + ComputeBaseSubobjectInfo(RD); + // If we have a primary base class, lay it out. if (PrimaryBase) { if (PrimaryBaseIsVirtual) { + // If the primary virtual base was a primary virtual base of some other + // base class we'll have to steal it. + BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase); + PrimaryBaseInfo->Derived = 0; + // We have a virtual primary base, insert it as an indirect primary base. IndirectPrimaryBases.insert(PrimaryBase); @@ -590,9 +929,15 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { "vbase already visited!"); VisitedVirtualBases.insert(PrimaryBase); - LayoutVirtualBase(PrimaryBase); - } else - LayoutNonVirtualBase(PrimaryBase); + LayoutVirtualBase(PrimaryBaseInfo); + } else { + BaseSubobjectInfo *PrimaryBaseInfo = + NonVirtualBaseInfo.lookup(PrimaryBase); + assert(PrimaryBaseInfo && + "Did not find base info for non-virtual primary base!"); + + LayoutNonVirtualBase(PrimaryBaseInfo); + } } // Now lay out the non-virtual bases. @@ -603,81 +948,64 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { if (I->isVirtual()) continue; - const CXXRecordDecl *Base = + const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); // Skip the primary base. - if (Base == PrimaryBase && !PrimaryBaseIsVirtual) + if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual) continue; // Lay out the base. - LayoutNonVirtualBase(Base); + BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.lookup(BaseDecl); + assert(BaseInfo && "Did not find base info for non-virtual base!"); + + LayoutNonVirtualBase(BaseInfo); } } -void RecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *Base) { +void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) { // Layout the base. - uint64_t Offset = LayoutBase(Base, /*BaseIsVirtual=*/false); + uint64_t Offset = LayoutBase(Base); // Add its base class offset. - if (!Bases.insert(std::make_pair(Base, Offset)).second) - assert(false && "Added same base offset more than once!"); + assert(!Bases.count(Base->Class) && "base offset already exists!"); + Bases.insert(std::make_pair(Base->Class, Offset)); + + AddPrimaryVirtualBaseOffsets(Base, Offset); } void -RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const CXXRecordDecl *RD, - uint64_t Offset, - const CXXRecordDecl *MostDerivedClass) { - // We already have the offset for the primary base of the most derived class. - if (RD != MostDerivedClass) { - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - - // If this is a primary virtual base and we haven't seen it before, add it. - if (PrimaryBase && Layout.getPrimaryBaseWasVirtual() && - !VBases.count(PrimaryBase)) - VBases.insert(std::make_pair(PrimaryBase, Offset)); +RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, + uint64_t Offset) { + // This base isn't interesting, it has no virtual bases. + if (!Info->Class->getNumVBases()) + return; + + // First, check if we have a virtual primary base to add offsets for. + if (Info->PrimaryVirtualBaseInfo) { + assert(Info->PrimaryVirtualBaseInfo->IsVirtual && + "Primary virtual base is not virtual!"); + if (Info->PrimaryVirtualBaseInfo->Derived == Info) { + // Add the offset. + assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) && + "primary vbase offset already exists!"); + VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class, + Offset)); + + // Traverse the primary virtual base. + AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset); + } } - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && - "Cannot layout class with dependent bases."); - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - if (!BaseDecl->getNumVBases()) { - // This base isn't interesting since it doesn't have any virtual bases. + // Now go through all direct non-virtual bases. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); + for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) { + const BaseSubobjectInfo *Base = Info->Bases[I]; + if (Base->IsVirtual) continue; - } - - // Compute the offset of this base. - uint64_t BaseOffset; - - if (I->isVirtual()) { - // If we don't know this vbase yet, don't visit it. It will be visited - // later. - if (!VBases.count(BaseDecl)) { - continue; - } - - // Check if we've already visited this base. - if (!VisitedVirtualBases.insert(BaseDecl)) - continue; - // We want the vbase offset from the class we're currently laying out. - BaseOffset = VBases[BaseDecl]; - } else if (RD == MostDerivedClass) { - // We want the base offset from the class we're currently laying out. - assert(Bases.count(BaseDecl) && "Did not find base!"); - BaseOffset = Bases[BaseDecl]; - } else { - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl); - } - - AddPrimaryVirtualBaseOffsets(BaseDecl, BaseOffset, MostDerivedClass); + uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class); + AddPrimaryVirtualBaseOffsets(Base, BaseOffset); } } @@ -701,53 +1029,54 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, assert(!I->getType()->isDependentType() && "Cannot layout class with dependent bases."); - const CXXRecordDecl *Base = + const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); if (I->isVirtual()) { - if (PrimaryBase != Base || !PrimaryBaseIsVirtual) { - bool IndirectPrimaryBase = IndirectPrimaryBases.count(Base); + if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) { + bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl); // Only lay out the virtual base if it's not an indirect primary base. if (!IndirectPrimaryBase) { // Only visit virtual bases once. - if (!VisitedVirtualBases.insert(Base)) + if (!VisitedVirtualBases.insert(BaseDecl)) continue; - LayoutVirtualBase(Base); + const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl); + assert(BaseInfo && "Did not find virtual base info!"); + LayoutVirtualBase(BaseInfo); } } } - if (!Base->getNumVBases()) { + if (!BaseDecl->getNumVBases()) { // This base isn't interesting since it doesn't have any virtual bases. continue; } - LayoutVirtualBases(Base, MostDerivedClass); + LayoutVirtualBases(BaseDecl, MostDerivedClass); } } -void RecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *Base) { +void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) { + assert(!Base->Derived && "Trying to lay out a primary virtual base!"); + // Layout the base. - uint64_t Offset = LayoutBase(Base, /*BaseIsVirtual=*/true); + uint64_t Offset = LayoutBase(Base); // Add its base class offset. - if (!VBases.insert(std::make_pair(Base, Offset)).second) - assert(false && "Added same vbase offset more than once!"); + assert(!VBases.count(Base->Class) && "vbase offset already exists!"); + VBases.insert(std::make_pair(Base->Class, Offset)); + + AddPrimaryVirtualBaseOffsets(Base, Offset); } -uint64_t RecordLayoutBuilder::LayoutBase(const CXXRecordDecl *Base, - bool BaseIsVirtual) { - const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base); +uint64_t RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class); // If we have an empty base class, try to place it at offset 0. - if (Base->isEmpty() && - EmptySubobjects->CanPlaceBaseAtOffset(Base, BaseIsVirtual, 0) && - canPlaceRecordAtOffset(Base, 0, /*CheckVBases=*/false)) { - // We were able to place the class at offset 0. - UpdateEmptyClassOffsets(Base, 0, /*UpdateVBases=*/false); - + if (Base->Class->isEmpty() && + EmptySubobjects->CanPlaceBaseAtOffset(Base, 0)) { Size = std::max(Size, Layout.getSize()); return 0; @@ -759,15 +1088,10 @@ uint64_t RecordLayoutBuilder::LayoutBase(const CXXRecordDecl *Base, uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign); // Try to place the base. - while (true) { - if (EmptySubobjects->CanPlaceBaseAtOffset(Base, BaseIsVirtual, Offset) && - canPlaceRecordAtOffset(Base, Offset, /*CheckVBases=*/false)) - break; - + while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset)) Offset += BaseAlign; - } - if (!Base->isEmpty()) { + if (!Base->Class->isEmpty()) { // Update the data size. DataSize = Offset + Layout.getNonVirtualSize(); @@ -778,173 +1102,9 @@ uint64_t RecordLayoutBuilder::LayoutBase(const CXXRecordDecl *Base, // Remember max struct/class alignment. UpdateAlignment(BaseAlign); - UpdateEmptyClassOffsets(Base, Offset, /*UpdateVBases=*/false); return Offset; } -bool -RecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD, - uint64_t Offset, - bool CheckVBases) const { - // Look for an empty class with the same type at the same offset. - for (EmptyClassOffsetsTy::const_iterator I = - EmptyClassOffsets.lower_bound(Offset), - E = EmptyClassOffsets.upper_bound(Offset); I != E; ++I) { - - if (I->second == RD) - return false; - } - - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - // Check bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && - "Cannot layout class with dependent bases."); - if (I->isVirtual()) - continue; - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl); - - if (!canPlaceRecordAtOffset(BaseDecl, Offset + BaseOffset, - /*CheckVBases=*/false)) - return false; - } - - // Check fields. - unsigned FieldNo = 0; - for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I, ++FieldNo) { - const FieldDecl *FD = *I; - - uint64_t FieldOffset = Layout.getFieldOffset(FieldNo); - - if (!canPlaceFieldAtOffset(FD, Offset + FieldOffset)) - return false; - } - - if (CheckVBases) { - // FIXME: virtual bases. - } - - return true; -} - -bool RecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD, - uint64_t Offset) const { - QualType T = FD->getType(); - if (const RecordType *RT = T->getAs<RecordType>()) { - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) - return canPlaceRecordAtOffset(RD, Offset, /*CheckVBases=*/true); - } - - if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) { - QualType ElemTy = Context.getBaseElementType(AT); - const RecordType *RT = ElemTy->getAs<RecordType>(); - if (!RT) - return true; - const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - if (!RD) - return true; - - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - uint64_t NumElements = Context.getConstantArrayElementCount(AT); - uint64_t ElementOffset = Offset; - for (uint64_t I = 0; I != NumElements; ++I) { - if (!canPlaceRecordAtOffset(RD, ElementOffset, /*CheckVBases=*/true)) - return false; - - ElementOffset += Layout.getSize(); - } - } - - return true; -} - -void RecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD, - uint64_t Offset, - bool UpdateVBases) { - if (RD->isEmpty()) - EmptyClassOffsets.insert(std::make_pair(Offset, RD)); - - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - // Update bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && - "Cannot layout class with dependent bases."); - if (I->isVirtual()) - continue; - - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - uint64_t BaseClassOffset = Layout.getBaseClassOffset(Base); - UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset, - /*UpdateVBases=*/false); - } - - // Update fields. - unsigned FieldNo = 0; - for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I, ++FieldNo) { - const FieldDecl *FD = *I; - - uint64_t FieldOffset = Layout.getFieldOffset(FieldNo); - UpdateEmptyClassOffsets(FD, Offset + FieldOffset); - } - - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - - if (UpdateVBases) { - // FIXME: Update virtual bases. - } else if (PrimaryBase && Layout.getPrimaryBaseWasVirtual()) { - // We always want to update the offsets of a primary virtual base. - assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 && - "primary base class offset must always be 0!"); - UpdateEmptyClassOffsets(PrimaryBase, Offset, /*UpdateVBases=*/false); - } -} - -void -RecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD, - uint64_t Offset) { - QualType T = FD->getType(); - - if (const RecordType *RT = T->getAs<RecordType>()) { - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - UpdateEmptyClassOffsets(RD, Offset, /*UpdateVBases=*/true); - return; - } - } - - if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) { - QualType ElemTy = Context.getBaseElementType(AT); - const RecordType *RT = ElemTy->getAs<RecordType>(); - if (!RT) - return; - const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - if (!RD) - return; - - const ASTRecordLayout &Info = Context.getASTRecordLayout(RD); - - uint64_t NumElements = Context.getConstantArrayElementCount(AT); - uint64_t ElementOffset = Offset; - - for (uint64_t I = 0; I != NumElements; ++I) { - UpdateEmptyClassOffsets(RD, ElementOffset, /*UpdateVBases=*/true); - ElementOffset += Info.getSize(); - } - } -} - void RecordLayoutBuilder::InitializeLayout(const Decl *D) { if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) IsUnion = RD->isUnion(); @@ -992,7 +1152,6 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { LayoutVirtualBases(RD, RD); VisitedVirtualBases.clear(); - AddPrimaryVirtualBaseOffsets(RD, 0, RD); // Finally, round the size of the total struct up to the alignment of the // struct itself. @@ -1137,7 +1296,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // Check if we need to add padding to give the field the correct alignment. if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) - FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1); + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); // Padding members don't affect overall alignment. if (!D->getIdentifier()) @@ -1208,17 +1367,12 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { // Round up the current record size to the field's alignment boundary. FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); - if (!IsUnion) { - while (true) { - // Check if we can place the field at this offset. - if (canPlaceFieldAtOffset(D, FieldOffset)) - break; - + if (!IsUnion && EmptySubobjects) { + // Check if we can place the field at this offset. + while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) { // We couldn't place the field at the offset. Try again at a new offset. FieldOffset += FieldAlign; } - - UpdateEmptyClassOffsets(D, FieldOffset); } // Place this field at the current location. @@ -1261,8 +1415,6 @@ void RecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { const CXXMethodDecl * RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { - assert(RD->isDynamicClass() && "Class does not have any virtual methods!"); - // If a class isn't polymorphic it doesn't have a key function. if (!RD->isPolymorphic()) return 0; diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index 80f5695..6dbe8f4 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -499,14 +499,101 @@ void DeclStmt::DoDestroy(ASTContext &C) { DG.getDeclGroup().Destroy(C); } +IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, + Stmt *then, SourceLocation EL, Stmt *elsev) + : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) +{ + setConditionVariable(C, var); + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[THEN] = then; + SubExprs[ELSE] = elsev; +} + +VarDecl *IfStmt::getConditionVariable() const { + if (!SubExprs[VAR]) + return 0; + + DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); + return cast<VarDecl>(DS->getSingleDecl()); +} + +void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[VAR] = 0; + return; + } + + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), + V->getSourceRange().getBegin(), + V->getSourceRange().getEnd()); +} + void IfStmt::DoDestroy(ASTContext &C) { BranchDestroy(C, this, SubExprs, END_EXPR); } +ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, + Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, + SourceLocation RP) + : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP) +{ + SubExprs[INIT] = Init; + setConditionVariable(C, condVar); + SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); + SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); + SubExprs[BODY] = Body; +} + +VarDecl *ForStmt::getConditionVariable() const { + if (!SubExprs[CONDVAR]) + return 0; + + DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]); + return cast<VarDecl>(DS->getSingleDecl()); +} + +void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[CONDVAR] = 0; + return; + } + + SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), + V->getSourceRange().getBegin(), + V->getSourceRange().getEnd()); +} + void ForStmt::DoDestroy(ASTContext &C) { BranchDestroy(C, this, SubExprs, END_EXPR); } +SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond) + : Stmt(SwitchStmtClass), FirstCase(0) +{ + setConditionVariable(C, Var); + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = NULL; +} + +VarDecl *SwitchStmt::getConditionVariable() const { + if (!SubExprs[VAR]) + return 0; + + DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); + return cast<VarDecl>(DS->getSingleDecl()); +} + +void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[VAR] = 0; + return; + } + + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), + V->getSourceRange().getBegin(), + V->getSourceRange().getEnd()); +} + void SwitchStmt::DoDestroy(ASTContext &C) { // Destroy the SwitchCase statements in this switch. In the normal // case, this loop will merely decrement the reference counts from @@ -521,6 +608,35 @@ void SwitchStmt::DoDestroy(ASTContext &C) { BranchDestroy(C, this, SubExprs, END_EXPR); } +WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, + SourceLocation WL) +: Stmt(WhileStmtClass) +{ + setConditionVariable(C, Var); + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = body; + WhileLoc = WL; +} + +VarDecl *WhileStmt::getConditionVariable() const { + if (!SubExprs[VAR]) + return 0; + + DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); + return cast<VarDecl>(DS->getSingleDecl()); +} + +void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[VAR] = 0; + return; + } + + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), + V->getSourceRange().getBegin(), + V->getSourceRange().getEnd()); +} + void WhileStmt::DoDestroy(ASTContext &C) { BranchDestroy(C, this, SubExprs, END_EXPR); } @@ -572,26 +688,26 @@ Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; } // IfStmt Stmt::child_iterator IfStmt::child_begin() { - return child_iterator(Var, &SubExprs[0]); + return &SubExprs[0]; } Stmt::child_iterator IfStmt::child_end() { - return child_iterator(0, &SubExprs[0]+END_EXPR); + return &SubExprs[0]+END_EXPR; } // SwitchStmt Stmt::child_iterator SwitchStmt::child_begin() { - return child_iterator(Var, &SubExprs[0]); + return &SubExprs[0]; } Stmt::child_iterator SwitchStmt::child_end() { - return child_iterator(0, &SubExprs[0]+END_EXPR); + return &SubExprs[0]+END_EXPR; } // WhileStmt Stmt::child_iterator WhileStmt::child_begin() { - return child_iterator(Var, &SubExprs[0]); + return &SubExprs[0]; } Stmt::child_iterator WhileStmt::child_end() { - return child_iterator(0, &SubExprs[0]+END_EXPR); + return &SubExprs[0]+END_EXPR; } // DoStmt @@ -600,10 +716,10 @@ Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; } // ForStmt Stmt::child_iterator ForStmt::child_begin() { - return child_iterator(CondVar, &SubExprs[0]); + return &SubExprs[0]; } Stmt::child_iterator ForStmt::child_end() { - return child_iterator(0, &SubExprs[0]+END_EXPR); + return &SubExprs[0]+END_EXPR; } // ObjCForCollectionStmt diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 9bef49c..7043c35 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -682,7 +682,7 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) { bool StmtPrinter::PrintOffsetOfDesignator(Expr *E) { if (isa<UnaryOperator>(E)) { // Base case, print the type and comma. - OS << E->getType().getAsString() << ", "; + OS << E->getType().getAsString(Policy) << ", "; return true; } else if (ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) { PrintOffsetOfDesignator(ASE->getLHS()); @@ -706,7 +706,7 @@ void StmtPrinter::VisitUnaryOffsetOf(UnaryOperator *Node) { void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) { OS << "__builtin_offsetof("; - OS << Node->getTypeSourceInfo()->getType().getAsString() << ", "; + OS << Node->getTypeSourceInfo()->getType().getAsString(Policy) << ", "; bool PrintedSomething = false; for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) { OffsetOfExpr::OffsetOfNode ON = Node->getComponent(i); @@ -740,7 +740,7 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) { void StmtPrinter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { OS << (Node->isSizeOf() ? "sizeof" : "__alignof"); if (Node->isArgumentType()) - OS << "(" << Node->getArgumentType().getAsString() << ")"; + OS << "(" << Node->getArgumentType().getAsString(Policy) << ")"; else { OS << " "; PrintExpr(Node->getArgumentExpr()); @@ -802,11 +802,11 @@ void StmtPrinter::VisitExplicitCastExpr(ExplicitCastExpr *) { assert(0 && "ExplicitCastExpr is an abstract class"); } void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) { - OS << "(" << Node->getType().getAsString() << ")"; + OS << "(" << Node->getType().getAsString(Policy) << ")"; PrintExpr(Node->getSubExpr()); } void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) { - OS << "(" << Node->getType().getAsString() << ")"; + OS << "(" << Node->getType().getAsString(Policy) << ")"; PrintExpr(Node->getInitializer()); } void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) { @@ -852,8 +852,8 @@ void StmtPrinter::VisitStmtExpr(StmtExpr *E) { void StmtPrinter::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) { OS << "__builtin_types_compatible_p("; - OS << Node->getArgType1().getAsString() << ","; - OS << Node->getArgType2().getAsString() << ")"; + OS << Node->getArgType1().getAsString(Policy) << ","; + OS << Node->getArgType2().getAsString(Policy) << ")"; } void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) { @@ -947,7 +947,7 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { OS << "__builtin_va_arg("; PrintExpr(Node->getSubExpr()); OS << ", "; - OS << Node->getType().getAsString(); + OS << Node->getType().getAsString(Policy); OS << ")"; } @@ -1002,7 +1002,7 @@ void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) { void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { OS << Node->getCastName() << '<'; - OS << Node->getTypeAsWritten().getAsString() << ">("; + OS << Node->getTypeAsWritten().getAsString(Policy) << ">("; PrintExpr(Node->getSubExpr()); OS << ")"; } @@ -1026,7 +1026,7 @@ void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) { void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) { OS << "typeid("; if (Node->isTypeOperand()) { - OS << Node->getTypeOperand().getAsString(); + OS << Node->getTypeOperand().getAsString(Policy); } else { PrintExpr(Node->getExprOperand()); } @@ -1059,7 +1059,7 @@ void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) { } void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { - OS << Node->getType().getAsString(); + OS << Node->getType().getAsString(Policy); OS << "("; PrintExpr(Node->getSubExpr()); OS << ")"; @@ -1074,7 +1074,7 @@ void StmtPrinter::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *Node) { } void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { - OS << Node->getType().getAsString(); + OS << Node->getType().getAsString(Policy); OS << "("; for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); @@ -1086,8 +1086,8 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { OS << ")"; } -void StmtPrinter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *Node) { - OS << Node->getType().getAsString() << "()"; +void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) { + OS << Node->getType().getAsString(Policy) << "()"; } void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { @@ -1177,7 +1177,7 @@ void StmtPrinter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { void StmtPrinter::VisitCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *Node) { - OS << Node->getTypeAsWritten().getAsString(); + OS << Node->getTypeAsWritten().getAsString(Policy); OS << "("; for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); @@ -1254,7 +1254,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) { void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { OS << getTypeTraitName(E->getTrait()) << "(" - << E->getQueriedType().getAsString() << ")"; + << E->getQueriedType().getAsString(Policy) << ")"; } // Obj-C @@ -1265,7 +1265,7 @@ void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) { } void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { - OS << "@encode(" << Node->getEncodedType().getAsString() << ')'; + OS << "@encode(" << Node->getEncodedType().getAsString(Policy) << ')'; } void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index ac3a9ee..cff86a4 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -211,9 +211,11 @@ void StmtProfiler::VisitExpr(Expr *S) { void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) { VisitExpr(S); - VisitNestedNameSpecifier(S->getQualifier()); + if (!Canonical) + VisitNestedNameSpecifier(S->getQualifier()); VisitDecl(S->getDecl()); - VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); + if (!Canonical) + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitPredefinedExpr(PredefinedExpr *S) { @@ -307,7 +309,8 @@ void StmtProfiler::VisitCallExpr(CallExpr *S) { void StmtProfiler::VisitMemberExpr(MemberExpr *S) { VisitExpr(S); VisitDecl(S->getMemberDecl()); - VisitNestedNameSpecifier(S->getQualifier()); + if (!Canonical) + VisitNestedNameSpecifier(S->getQualifier()); ID.AddBoolean(S->isArrow()); } @@ -428,6 +431,8 @@ void StmtProfiler::VisitBlockDeclRefExpr(BlockDeclRefExpr *S) { VisitDecl(S->getDecl()); ID.AddBoolean(S->isByRef()); ID.AddBoolean(S->isConstQualAdded()); + if (S->getCopyConstructorExpr()) + Visit(S->getCopyConstructorExpr()); } static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S, @@ -719,7 +724,7 @@ void StmtProfiler::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *S) { VisitCXXConstructExpr(S); } -void StmtProfiler::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *S) { +void StmtProfiler::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *S) { VisitExpr(S); } diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index 1c775ef..02e6488 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -90,6 +90,33 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, } } +bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { + if (getKind() != Other.getKind()) return false; + + switch (getKind()) { + case Null: + case Type: + case Declaration: + case Template: + case Expression: + return TypeOrValue == Other.TypeOrValue; + + case Integral: + return getIntegralType() == Other.getIntegralType() && + *getAsIntegral() == *Other.getAsIntegral(); + + case Pack: + if (Args.NumArgs != Other.Args.NumArgs) return false; + for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) + if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) + return false; + return true; + } + + // Suppress warnings. + return false; +} + //===----------------------------------------------------------------------===// // TemplateArgumentLoc Implementation //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp index 14722f7..ef7b315 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp @@ -21,6 +21,17 @@ using namespace clang; using namespace llvm; +TemplateName::NameKind TemplateName::getKind() const { + if (Storage.is<TemplateDecl *>()) + return Template; + if (Storage.is<OverloadedTemplateStorage *>()) + return OverloadedTemplate; + if (Storage.is<QualifiedTemplateName *>()) + return QualifiedTemplate; + assert(Storage.is<DependentTemplateName *>() && "There's a case unhandled!"); + return DependentTemplate; +} + TemplateDecl *TemplateName::getAsTemplateDecl() const { if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) return Template; diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 1aab65e..d7929304 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -439,17 +439,49 @@ bool Type::isIntegerType() const { return false; } -bool Type::isIntegralType() const { +/// \brief Determine whether this type is an integral type. +/// +/// This routine determines whether the given type is an integral type per +/// C++ [basic.fundamental]p7. Although the C standard does not define the +/// term "integral type", it has a similar term "integer type", and in C++ +/// the two terms are equivalent. However, C's "integer type" includes +/// enumeration types, while C++'s "integer type" does not. The \c ASTContext +/// parameter is used to determine whether we should be following the C or +/// C++ rules when determining whether this type is an integral/integer type. +/// +/// For cases where C permits "an integer type" and C++ permits "an integral +/// type", use this routine. +/// +/// For cases where C permits "an integer type" and C++ permits "an integral +/// or enumeration type", use \c isIntegralOrEnumerationType() instead. +/// +/// \param Ctx The context in which this type occurs. +/// +/// \returns true if the type is considered an integral type, false otherwise. +bool Type::isIntegralType(ASTContext &Ctx) const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; - if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) - if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition()) - return true; // Complete enum types are integral. - // FIXME: In C++, enum types are never integral. + + if (!Ctx.getLangOptions().CPlusPlus) + if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) + if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition()) + return true; // Complete enum types are integral in C. + return false; } +bool Type::isIntegralOrEnumerationType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::Int128; + + if (isa<EnumType>(CanonicalType)) + return true; + + return false; +} + bool Type::isEnumeralType() const { if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) return TT->getDecl()->isEnum(); @@ -531,16 +563,19 @@ bool Type::isFloatingType() const { BT->getKind() <= BuiltinType::LongDouble; if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType)) return CT->getElementType()->isFloatingType(); + return false; +} + +bool Type::hasFloatingRepresentation() const { if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isFloatingType(); - return false; + else + return isFloatingType(); } bool Type::isRealFloatingType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->isFloatingPoint(); - if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) - return VT->getElementType()->isRealFloatingType(); return false; } @@ -550,8 +585,6 @@ bool Type::isRealType() const { BT->getKind() <= BuiltinType::LongDouble; if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) return TT->getDecl()->isEnum() && TT->getDecl()->isDefinition(); - if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) - return VT->getElementType()->isRealType(); return false; } @@ -563,7 +596,7 @@ bool Type::isArithmeticType() const { // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). // If a body isn't seen by the time we get here, return false. return ET->getDecl()->isDefinition(); - return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType); + return isa<ComplexType>(CanonicalType); } bool Type::isScalarType() const { @@ -768,6 +801,7 @@ bool Type::isSpecifierType() const { case TemplateSpecialization: case Elaborated: case DependentName: + case DependentTemplateSpecialization: case ObjCInterface: case ObjCObject: case ObjCObjectPointer: // FIXME: object pointers aren't really specifiers @@ -856,12 +890,56 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { } } +ElaboratedType::~ElaboratedType() {} +DependentNameType::~DependentNameType() {} +DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {} + +void DependentTemplateSpecializationType::Destroy(ASTContext &C) { + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + // FIXME: Not all expressions get cloned, so we can't yet perform + // this destruction. + // if (Expr *E = getArg(Arg).getAsExpr()) + // E->Destroy(C); + } +} + +DependentTemplateSpecializationType::DependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, const IdentifierInfo *Name, + unsigned NumArgs, const TemplateArgument *Args, + QualType Canon) + : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true), + NNS(NNS), Name(Name), NumArgs(NumArgs) { + assert(NNS && NNS->isDependent() && + "DependentTemplateSpecializatonType requires dependent qualifier"); + for (unsigned I = 0; I != NumArgs; ++I) + new (&getArgBuffer()[I]) TemplateArgument(Args[I]); +} + +void +DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, + ASTContext &Context, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args) { + ID.AddInteger(Keyword); + ID.AddPointer(Qualifier); + ID.AddPointer(Name); + for (unsigned Idx = 0; Idx < NumArgs; ++Idx) + Args[Idx].Profile(ID, Context); +} + bool Type::isElaboratedTypeSpecifier() const { ElaboratedTypeKeyword Keyword; if (const ElaboratedType *Elab = dyn_cast<ElaboratedType>(this)) Keyword = Elab->getKeyword(); else if (const DependentNameType *DepName = dyn_cast<DependentNameType>(this)) Keyword = DepName->getKeyword(); + else if (const DependentTemplateSpecializationType *DepTST = + dyn_cast<DependentTemplateSpecializationType>(this)) + Keyword = DepTST->getKeyword(); else return false; @@ -914,6 +992,22 @@ const char *BuiltinType::getName(const LangOptions &LO) const { void FunctionType::ANCHOR() {} // Key function for FunctionType. +QualType QualType::getNonLValueExprType(ASTContext &Context) const { + if (const ReferenceType *RefType = getTypePtr()->getAs<ReferenceType>()) + return RefType->getPointeeType(); + + // C++0x [basic.lval]: + // Class prvalues can have cv-qualified types; non-class prvalues always + // have cv-unqualified types. + // + // See also C99 6.3.2.1p2. + if (!Context.getLangOptions().CPlusPlus || + (!getTypePtr()->isDependentType() && !getTypePtr()->isRecordType())) + return getUnqualifiedType(); + + return *this; +} + llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) { switch (CC) { case CC_Default: llvm_unreachable("no name for default cc"); @@ -1085,14 +1179,12 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) { } TemplateSpecializationType:: -TemplateSpecializationType(ASTContext &Context, TemplateName T, - bool IsCurrentInstantiation, +TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, QualType Canon) : Type(TemplateSpecialization, Canon.isNull()? QualType(this, 0) : Canon, T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)), - ContextAndCurrentInstantiation(&Context, IsCurrentInstantiation), Template(T), NumArgs(NumArgs) { assert((!Canon.isNull() || T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) && @@ -1113,25 +1205,12 @@ void TemplateSpecializationType::Destroy(ASTContext& C) { } } -TemplateSpecializationType::iterator -TemplateSpecializationType::end() const { - return begin() + getNumArgs(); -} - -const TemplateArgument & -TemplateSpecializationType::getArg(unsigned Idx) const { - assert(Idx < getNumArgs() && "Template argument out of range"); - return getArgs()[Idx]; -} - void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - bool IsCurrentInstantiation, const TemplateArgument *Args, unsigned NumArgs, ASTContext &Context) { - ID.AddBoolean(IsCurrentInstantiation); T.Profile(ID); for (unsigned Idx = 0; Idx < NumArgs; ++Idx) Args[Idx].Profile(ID, Context); diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index 35a7e09..a08ee1a 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -227,12 +227,13 @@ void TypePrinter::PrintDependentSizedExtVector( } void TypePrinter::PrintVector(const VectorType *T, std::string &S) { - if (T->isAltiVec()) { - if (T->isPixel()) + if (T->getAltiVecSpecific() != VectorType::NotAltiVec) { + if (T->getAltiVecSpecific() == VectorType::Pixel) S = "__vector __pixel " + S; else { Print(T->getElementType(), S); - S = "__vector " + S; + S = ((T->getAltiVecSpecific() == VectorType::Bool) + ? "__vector __bool " : "__vector ") + S; } } else { // FIXME: We prefer to print the size directly here, but have no way @@ -452,11 +453,13 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) { if (!HasKindDecoration) OS << " " << D->getKindName(); - PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( - D->getLocation()); - OS << " at " << PLoc.getFilename() - << ':' << PLoc.getLine() - << ':' << PLoc.getColumn(); + if (D->getLocation().isValid()) { + PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( + D->getLocation()); + OS << " at " << PLoc.getFilename() + << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); + } } OS << '>'; @@ -578,15 +581,31 @@ void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) T->getQualifier()->print(OS, Policy); - if (const IdentifierInfo *Ident = T->getIdentifier()) - OS << Ident->getName(); - else if (const TemplateSpecializationType *Spec = T->getTemplateId()) { - Spec->getTemplateName().print(OS, Policy, true); - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Spec->getArgs(), - Spec->getNumArgs(), + OS << T->getIdentifier()->getName(); + } + + if (S.empty()) + S.swap(MyString); + else + S = MyString + ' ' + S; +} + +void TypePrinter::PrintDependentTemplateSpecialization( + const DependentTemplateSpecializationType *T, std::string &S) { + std::string MyString; + { + llvm::raw_string_ostream OS(MyString); + + OS << TypeWithKeyword::getKeywordName(T->getKeyword()); + if (T->getKeyword() != ETK_None) + OS << " "; + + T->getQualifier()->print(OS, Policy); + OS << T->getIdentifier()->getName(); + OS << TemplateSpecializationType::PrintTemplateArgumentList( + T->getArgs(), + T->getNumArgs(), Policy); - } } if (S.empty()) |