diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
40 files changed, 5414 insertions, 1512 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index ebe99b1..6f63a32 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -13,7 +13,10 @@ #include "clang/AST/APValue.h" #include "clang/AST/CharUnits.h" +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; namespace { @@ -89,9 +92,9 @@ static double GetApproxValue(const llvm::APFloat &F) { return V.convertToDouble(); } -void APValue::print(llvm::raw_ostream &OS) const { +void APValue::print(raw_ostream &OS) const { switch (getKind()) { - default: assert(0 && "Unknown APValue kind!"); + default: llvm_unreachable("Unknown APValue kind!"); case Uninitialized: OS << "Uninitialized"; return; @@ -118,6 +121,49 @@ void APValue::print(llvm::raw_ostream &OS) const { } } +static void WriteShortAPValueToStream(raw_ostream& Out, + const APValue& V) { + switch (V.getKind()) { + default: llvm_unreachable("Unknown APValue kind!"); + case APValue::Uninitialized: + Out << "Uninitialized"; + break; + case APValue::Int: + Out << V.getInt(); + break; + case APValue::Float: + Out << GetApproxValue(V.getFloat()); + break; + case APValue::Vector: + Out << '['; + WriteShortAPValueToStream(Out, V.getVectorElt(0)); + for (unsigned i = 1; i != V.getVectorLength(); ++i) { + Out << ", "; + WriteShortAPValueToStream(Out, V.getVectorElt(i)); + } + Out << ']'; + break; + case APValue::ComplexInt: + Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i"; + break; + case APValue::ComplexFloat: + Out << GetApproxValue(V.getComplexFloatReal()) << "+" + << GetApproxValue(V.getComplexFloatImag()) << "i"; + break; + case APValue::LValue: + Out << "LValue: <todo>"; + break; + } +} + +const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, + const APValue &V) { + llvm::SmallString<64> Buffer; + llvm::raw_svector_ostream Out(Buffer); + WriteShortAPValueToStream(Out, V); + return DB << Out.str(); +} + const Expr* APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); return ((const LV*)(const void*)Data)->Base; diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 6eada6e..4624280 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -30,6 +30,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Capacity.h" #include "CXXABI.h" #include <map> @@ -49,7 +50,7 @@ unsigned ASTContext::NumImplicitDestructors; unsigned ASTContext::NumImplicitDestructorsDeclared; enum FloatingRank { - FloatRank, DoubleRank, LongDoubleRank + HalfRank, FloatRank, DoubleRank, LongDoubleRank }; void @@ -104,7 +105,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( // Build a canonical template parameter list. TemplateParameterList *Params = TTP->getTemplateParameters(); - llvm::SmallVector<NamedDecl *, 4> CanonParams; + SmallVector<NamedDecl *, 4> CanonParams; CanonParams.reserve(Params->size()); for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); @@ -123,8 +124,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T); NonTypeTemplateParmDecl *Param; if (NTTP->isExpandedParameterPack()) { - llvm::SmallVector<QualType, 2> ExpandedTypes; - llvm::SmallVector<TypeSourceInfo *, 2> ExpandedTInfos; + SmallVector<QualType, 2> ExpandedTypes; + SmallVector<TypeSourceInfo *, 2> ExpandedTInfos; for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) { ExpandedTypes.push_back(getCanonicalType(NTTP->getExpansionType(I))); ExpandedTInfos.push_back( @@ -195,7 +196,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { return 0; } -static const LangAS::Map &getAddressSpaceMap(const TargetInfo &T, +static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, const LangOptions &LOpts) { if (LOpts.FakeAddressSpaceMap) { // The fake address space map must have a distinct entry for each @@ -205,41 +206,46 @@ static const LangAS::Map &getAddressSpaceMap(const TargetInfo &T, 2, // opencl_local 3 // opencl_constant }; - return FakeAddrSpaceMap; + return &FakeAddrSpaceMap; } else { - return T.getAddressSpaceMap(); + return &T.getAddressSpaceMap(); } } -ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, - const TargetInfo &t, +ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, + const TargetInfo *t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, - unsigned size_reserve) : - FunctionProtoTypes(this_()), - TemplateSpecializationTypes(this_()), - DependentTemplateSpecializationTypes(this_()), - SubstTemplateTemplateParmPacks(this_()), - GlobalNestedNameSpecifier(0), IsInt128Installed(false), - CFConstantStringTypeDecl(0), NSConstantStringTypeDecl(0), - ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), - jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0), - BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0), - NullTypeSourceInfo(QualType()), - SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)), - AddrSpaceMap(getAddressSpaceMap(t, LOpts)), Target(t), - Idents(idents), Selectors(sels), - BuiltinInfo(builtins), - DeclarationNames(*this), - ExternalSource(0), Listener(0), PrintingPolicy(LOpts), - LastSDM(0, 0), - UniqueBlockByRefTypeID(0) { - ObjCIdRedefinitionType = QualType(); - ObjCClassRedefinitionType = QualType(); - ObjCSelRedefinitionType = QualType(); + unsigned size_reserve, + bool DelayInitialization) + : FunctionProtoTypes(this_()), + TemplateSpecializationTypes(this_()), + DependentTemplateSpecializationTypes(this_()), + SubstTemplateTemplateParmPacks(this_()), + GlobalNestedNameSpecifier(0), + Int128Decl(0), UInt128Decl(0), + ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), + CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0), + FILEDecl(0), + jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0), + BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0), + NullTypeSourceInfo(QualType()), + SourceMgr(SM), LangOpts(LOpts), + AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts), + Idents(idents), Selectors(sels), + BuiltinInfo(builtins), + DeclarationNames(*this), + ExternalSource(0), Listener(0), + LastSDM(0, 0), + UniqueBlockByRefTypeID(0) +{ if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); - InitBuiltinTypes(); + + if (!DelayInitialization) { + assert(t && "No target supplied for ASTContext initialization"); + InitBuiltinTypes(*t); + } } ASTContext::~ASTContext() { @@ -347,6 +353,33 @@ void ASTContext::PrintStats() const { BumpAlloc.PrintStats(); } +TypedefDecl *ASTContext::getInt128Decl() const { + if (!Int128Decl) { + TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(Int128Ty); + Int128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this), + getTranslationUnitDecl(), + SourceLocation(), + SourceLocation(), + &Idents.get("__int128_t"), + TInfo); + } + + return Int128Decl; +} + +TypedefDecl *ASTContext::getUInt128Decl() const { + if (!UInt128Decl) { + TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(UnsignedInt128Ty); + UInt128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this), + getTranslationUnitDecl(), + SourceLocation(), + SourceLocation(), + &Idents.get("__uint128_t"), + TInfo); + } + + return UInt128Decl; +} void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); @@ -354,9 +387,16 @@ void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { Types.push_back(Ty); } -void ASTContext::InitBuiltinTypes() { +void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { + assert((!this->Target || this->Target == &Target) && + "Incorrect target reinitialization"); assert(VoidTy.isNull() && "Context reinitialized?"); + this->Target = &Target; + + ABI.reset(createCXXABI(Target)); + AddrSpaceMap = getAddressSpaceMap(Target, LangOpts); + // C99 6.2.5p19. InitBuiltinType(VoidTy, BuiltinType::Void); @@ -431,11 +471,6 @@ void ASTContext::InitBuiltinTypes() { BuiltinVaListType = QualType(); - // "Builtin" typedefs set by Sema::ActOnTranslationUnitScope(). - ObjCIdTypedefType = QualType(); - ObjCClassTypedefType = QualType(); - ObjCSelTypedefType = QualType(); - // Builtin types for 'id', 'Class', and 'SEL'. InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId); InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass); @@ -448,9 +483,12 @@ void ASTContext::InitBuiltinTypes() { // nullptr type (C++0x 2.14.7) InitBuiltinType(NullPtrTy, BuiltinType::NullPtr); + + // half type (OpenCL 6.1.1.1) / ARM NEON __fp16 + InitBuiltinType(HalfTy, BuiltinType::Half); } -Diagnostic &ASTContext::getDiagnostics() const { +DiagnosticsEngine &ASTContext::getDiagnostics() const { return SourceMgr.getDiagnostics(); } @@ -496,6 +534,24 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, = new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation); } +FunctionDecl *ASTContext::getClassScopeSpecializationPattern( + const FunctionDecl *FD){ + assert(FD && "Specialization is 0"); + llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos + = ClassScopeSpecializationPattern.find(FD); + if (Pos == ClassScopeSpecializationPattern.end()) + return 0; + + return Pos->second; +} + +void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD, + FunctionDecl *Pattern) { + assert(FD && "Specialization is 0"); + assert(Pattern && "Class scope specialization pattern is 0"); + ClassScopeSpecializationPattern[FD] = Pattern; +} + NamedDecl * ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos @@ -555,35 +611,33 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && !LastFD->isBitField() && - FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0); - + FD->getBitWidthValue(*this) == 0); } bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0 && - LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() != 0); - + FD->getBitWidthValue(*this) == 0 && + LastFD->getBitWidthValue(*this) != 0); } bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() && - LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue()); + FD->getBitWidthValue(*this) && + LastFD->getBitWidthValue(*this)); } -bool ASTContext::NoneBitfieldFollowsBitfield(const FieldDecl *FD, +bool ASTContext::NonBitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (!FD->isBitField() && LastFD && LastFD->isBitField() && - LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue()); + LastFD->getBitWidthValue(*this)); } -bool ASTContext::BitfieldFollowsNoneBitfield(const FieldDecl *FD, +bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const { return (FD->isBitField() && LastFD && !LastFD->isBitField() && - FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue()); + FD->getBitWidthValue(*this)); } ASTContext::overridden_cxx_method_iterator @@ -631,10 +685,11 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { const BuiltinType *BT = T->getAs<BuiltinType>(); assert(BT && "Not a floating point type!"); switch (BT->getKind()) { - default: assert(0 && "Not a floating point type!"); - case BuiltinType::Float: return Target.getFloatFormat(); - case BuiltinType::Double: return Target.getDoubleFormat(); - case BuiltinType::LongDouble: return Target.getLongDoubleFormat(); + default: llvm_unreachable("Not a floating point type!"); + case BuiltinType::Half: return Target->getHalfFormat(); + case BuiltinType::Float: return Target->getFloatFormat(); + case BuiltinType::Double: return Target->getDoubleFormat(); + case BuiltinType::LongDouble: return Target->getLongDoubleFormat(); } } @@ -644,7 +699,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { /// If @p RefAsPointee, references are treated like their underlying type /// (for alignof), else they're treated like pointers (for CodeGen). CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { - unsigned Align = Target.getCharWidth(); + unsigned Align = Target->getCharWidth(); bool UseAlignAttrOnly = false; if (unsigned AlignFromAttr = D->getMaxAlignment()) { @@ -654,7 +709,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { // *except* on a struct or struct member, where it only increases // alignment unless 'packed' is also specified. // - // It is an error for [[align]] to decrease alignment, so we can + // It is an error for alignas to decrease alignment, so we can // ignore that possibility; Sema should diagnose it. if (isa<FieldDecl>(D)) { UseAlignAttrOnly = D->hasAttr<PackedAttr>() || @@ -684,14 +739,14 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { if (!T->isIncompleteType() && !T->isFunctionType()) { // Adjust alignments of declarations with array type by the // large-array alignment on the target. - unsigned MinWidth = Target.getLargeArrayMinWidth(); + unsigned MinWidth = Target->getLargeArrayMinWidth(); const ArrayType *arrayType; if (MinWidth && (arrayType = getAsArrayType(T))) { if (isa<VariableArrayType>(arrayType)) - Align = std::max(Align, Target.getLargeArrayAlign()); + Align = std::max(Align, Target->getLargeArrayAlign()); else if (isa<ConstantArrayType>(arrayType) && MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType))) - Align = std::max(Align, Target.getLargeArrayAlign()); + Align = std::max(Align, Target->getLargeArrayAlign()); // Walk through any array types while we're at it. T = getBaseElementType(arrayType); @@ -798,7 +853,7 @@ ASTContext::getTypeInfo(const Type *T) const { case Type::Builtin: switch (cast<BuiltinType>(T)->getKind()) { - default: assert(0 && "Unknown builtin type!"); + default: llvm_unreachable("Unknown builtin type!"); case BuiltinType::Void: // GCC extension: alignof(void) = 8 bits. Width = 0; @@ -806,87 +861,91 @@ ASTContext::getTypeInfo(const Type *T) const { break; case BuiltinType::Bool: - Width = Target.getBoolWidth(); - Align = Target.getBoolAlign(); + Width = Target->getBoolWidth(); + Align = Target->getBoolAlign(); break; case BuiltinType::Char_S: case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::SChar: - Width = Target.getCharWidth(); - Align = Target.getCharAlign(); + Width = Target->getCharWidth(); + Align = Target->getCharAlign(); break; case BuiltinType::WChar_S: case BuiltinType::WChar_U: - Width = Target.getWCharWidth(); - Align = Target.getWCharAlign(); + Width = Target->getWCharWidth(); + Align = Target->getWCharAlign(); break; case BuiltinType::Char16: - Width = Target.getChar16Width(); - Align = Target.getChar16Align(); + Width = Target->getChar16Width(); + Align = Target->getChar16Align(); break; case BuiltinType::Char32: - Width = Target.getChar32Width(); - Align = Target.getChar32Align(); + Width = Target->getChar32Width(); + Align = Target->getChar32Align(); break; case BuiltinType::UShort: case BuiltinType::Short: - Width = Target.getShortWidth(); - Align = Target.getShortAlign(); + Width = Target->getShortWidth(); + Align = Target->getShortAlign(); break; case BuiltinType::UInt: case BuiltinType::Int: - Width = Target.getIntWidth(); - Align = Target.getIntAlign(); + Width = Target->getIntWidth(); + Align = Target->getIntAlign(); break; case BuiltinType::ULong: case BuiltinType::Long: - Width = Target.getLongWidth(); - Align = Target.getLongAlign(); + Width = Target->getLongWidth(); + Align = Target->getLongAlign(); break; case BuiltinType::ULongLong: case BuiltinType::LongLong: - Width = Target.getLongLongWidth(); - Align = Target.getLongLongAlign(); + Width = Target->getLongLongWidth(); + Align = Target->getLongLongAlign(); break; case BuiltinType::Int128: case BuiltinType::UInt128: Width = 128; Align = 128; // int128_t is 128-bit aligned on all targets. break; + case BuiltinType::Half: + Width = Target->getHalfWidth(); + Align = Target->getHalfAlign(); + break; case BuiltinType::Float: - Width = Target.getFloatWidth(); - Align = Target.getFloatAlign(); + Width = Target->getFloatWidth(); + Align = Target->getFloatAlign(); break; case BuiltinType::Double: - Width = Target.getDoubleWidth(); - Align = Target.getDoubleAlign(); + Width = Target->getDoubleWidth(); + Align = Target->getDoubleAlign(); break; case BuiltinType::LongDouble: - Width = Target.getLongDoubleWidth(); - Align = Target.getLongDoubleAlign(); + Width = Target->getLongDoubleWidth(); + Align = Target->getLongDoubleAlign(); break; case BuiltinType::NullPtr: - Width = Target.getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t) - Align = Target.getPointerAlign(0); // == sizeof(void*) + Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t) + Align = Target->getPointerAlign(0); // == sizeof(void*) break; case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: - Width = Target.getPointerWidth(0); - Align = Target.getPointerAlign(0); + Width = Target->getPointerWidth(0); + Align = Target->getPointerAlign(0); break; } break; case Type::ObjCObjectPointer: - Width = Target.getPointerWidth(0); - Align = Target.getPointerAlign(0); + Width = Target->getPointerWidth(0); + Align = Target->getPointerAlign(0); break; case Type::BlockPointer: { unsigned AS = getTargetAddressSpace( cast<BlockPointerType>(T)->getPointeeType()); - Width = Target.getPointerWidth(AS); - Align = Target.getPointerAlign(AS); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); break; } case Type::LValueReference: @@ -895,14 +954,14 @@ ASTContext::getTypeInfo(const Type *T) const { // the pointer route. unsigned AS = getTargetAddressSpace( cast<ReferenceType>(T)->getPointeeType()); - Width = Target.getPointerWidth(AS); - Align = Target.getPointerAlign(AS); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); break; } case Type::Pointer: { unsigned AS = getTargetAddressSpace(cast<PointerType>(T)->getPointeeType()); - Width = Target.getPointerWidth(AS); - Align = Target.getPointerAlign(AS); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); break; } case Type::MemberPointer: { @@ -1012,9 +1071,26 @@ ASTContext::getTypeInfo(const Type *T) const { return getTypeInfo(getCanonicalType(T)); } + case Type::Atomic: { + std::pair<uint64_t, unsigned> Info + = getTypeInfo(cast<AtomicType>(T)->getValueType()); + Width = Info.first; + Align = Info.second; + if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth() && + llvm::isPowerOf2_64(Width)) { + // We can potentially perform lock-free atomic operations for this + // type; promote the alignment appropriately. + // FIXME: We could potentially promote the width here as well... + // is that worthwhile? (Non-struct atomic types generally have + // power-of-two size anyway, but structs might not. Requires a bit + // of implementation work to make sure we zero out the extra bits.) + Align = static_cast<unsigned>(Width); + } + } + } - assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2"); + assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2"); return std::make_pair(Width, Align); } @@ -1063,19 +1139,6 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { return ABIAlign; } -/// ShallowCollectObjCIvars - -/// Collect all ivars, including those synthesized, in the current class. -/// -void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const { - // FIXME. This need be removed but there are two many places which - // assume const-ness of ObjCInterfaceDecl - ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI); - for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; - Iv= Iv->getNextIvar()) - Ivars.push_back(Iv); -} - /// DeepCollectObjCIvars - /// This routine first collects all declared, but not synthesized, ivars in /// super class and then collects all ivars, including those synthesized for @@ -1084,17 +1147,16 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, /// void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, - llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const { + SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const { if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass()) DeepCollectObjCIvars(SuperClass, false, Ivars); if (!leafClass) { for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), E = OI->ivar_end(); I != E; ++I) Ivars.push_back(*I); - } - else { + } else { ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI); - for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; + for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; Iv= Iv->getNextIvar()) Ivars.push_back(Iv); } @@ -1562,7 +1624,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, // the target. llvm::APInt ArySize(ArySizeIn); ArySize = - ArySize.zextOrTrunc(Target.getPointerWidth(getTargetAddressSpace(EltTy))); + ArySize.zextOrTrunc(Target->getPointerWidth(getTargetAddressSpace(EltTy))); llvm::FoldingSetNodeID ID; ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals); @@ -1670,6 +1732,12 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { break; } + case Type::Atomic: { + const AtomicType *at = cast<AtomicType>(ty); + result = getAtomicType(getVariableArrayDecayedType(at->getValueType())); + break; + } + case Type::ConstantArray: { const ConstantArrayType *cat = cast<ConstantArrayType>(ty); result = getConstantArrayType( @@ -2026,7 +2094,7 @@ ASTContext::getFunctionType(QualType ResultTy, // The exception spec is not part of the canonical type. QualType Canonical; if (!isCanonical || getCanonicalCallConv(CallConv) != CallConv) { - llvm::SmallVector<QualType, 16> CanonicalArgs; + SmallVector<QualType, 16> CanonicalArgs; CanonicalArgs.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); @@ -2322,7 +2390,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, unsigned NumArgs = Args.size(); - llvm::SmallVector<TemplateArgument, 4> ArgVec; + SmallVector<TemplateArgument, 4> ArgVec; ArgVec.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) ArgVec.push_back(Args[i].getArgument()); @@ -2389,7 +2457,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, // Build the canonical template specialization type. TemplateName CanonTemplate = getCanonicalTemplateName(Template); - llvm::SmallVector<TemplateArgument, 4> CanonArgs; + SmallVector<TemplateArgument, 4> CanonArgs; CanonArgs.reserve(NumArgs); for (unsigned I = 0; I != NumArgs; ++I) CanonArgs.push_back(getCanonicalTemplateArgument(Args[I])); @@ -2509,7 +2577,7 @@ ASTContext::getDependentTemplateSpecializationType( const IdentifierInfo *Name, const TemplateArgumentListInfo &Args) const { // TODO: avoid this copy - llvm::SmallVector<TemplateArgument, 16> ArgCopy; + 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, @@ -2543,7 +2611,7 @@ ASTContext::getDependentTemplateSpecializationType( if (Keyword == ETK_None) CanonKeyword = ETK_Typename; bool AnyNonCanonArgs = false; - llvm::SmallVector<TemplateArgument, 16> CanonArgs(NumArgs); + SmallVector<TemplateArgument, 16> CanonArgs(NumArgs); for (unsigned I = 0; I != NumArgs; ++I) { CanonArgs[I] = getCanonicalTemplateArgument(Args[I]); if (!CanonArgs[I].structurallyEquals(Args[I])) @@ -2647,7 +2715,7 @@ QualType ASTContext::getObjCObjectType(QualType BaseType, bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols); if (!ProtocolsSorted || !BaseType.isCanonical()) { if (!ProtocolsSorted) { - llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols, + SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols, Protocols + NumProtocols); unsigned UniqueCount = NumProtocols; @@ -2737,8 +2805,7 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { // typeof(expr) type. Use that as our canonical type. toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr, QualType((TypeOfExprType*)Canon, 0)); - } - else { + } else { // Build a new, canonical typeof(expr) type. Canon = new (*this, TypeAlignment) DependentTypeOfExprType(*this, tofExpr); @@ -2821,8 +2888,7 @@ QualType ASTContext::getDecltypeType(Expr *e) const { // decltype type. Use that as our canonical type. dt = new (*this, TypeAlignment) DecltypeType(e, DependentTy, QualType((DecltypeType*)Canon, 0)); - } - else { + } else { // Build a new, canonical typeof(expr) type. Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e); DependentDecltypeTypes.InsertNode(Canon, InsertPos); @@ -2869,6 +2935,34 @@ QualType ASTContext::getAutoType(QualType DeducedType) const { return QualType(AT, 0); } +/// getAtomicType - Return the uniqued reference to the atomic type for +/// the given value type. +QualType ASTContext::getAtomicType(QualType T) const { + // Unique pointers, to guarantee there is only one pointer of a particular + // structure. + llvm::FoldingSetNodeID ID; + AtomicType::Profile(ID, T); + + void *InsertPos = 0; + if (AtomicType *AT = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(AT, 0); + + // If the atomic value type isn't canonical, this won't be a canonical type + // either, so fill in the canonical type field. + QualType Canonical; + if (!T.isCanonical()) { + Canonical = getAtomicType(getCanonicalType(T)); + + // Get the new insert position for the node we care about. + AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + } + AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical); + Types.push_back(New); + AtomicTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + /// getAutoDeductType - Get type pattern for deducing against 'auto'. QualType ASTContext::getAutoDeductType() const { if (AutoDeductTy.isNull()) @@ -2898,7 +2992,7 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) const { /// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and /// needs to agree with the definition in <stddef.h>. CanQualType ASTContext::getSizeType() const { - return getFromTargetType(Target.getSizeType()); + return getFromTargetType(Target->getSizeType()); } /// getSignedWCharType - Return the type of "signed wchar_t". @@ -2918,7 +3012,7 @@ QualType ASTContext::getUnsignedWCharType() const { /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?) /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType ASTContext::getPointerDiffType() const { - return getFromTargetType(Target.getPtrDiffType(0)); + return getFromTargetType(Target->getPtrDiffType(0)); } //===----------------------------------------------------------------------===// @@ -3183,8 +3277,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { } // Silence GCC warning - assert(false && "Unhandled template argument kind"); - return TemplateArgument(); + llvm_unreachable("Unhandled template argument kind"); } NestedNameSpecifier * @@ -3397,7 +3490,8 @@ static FloatingRank getFloatingRank(QualType T) { assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type"); switch (T->getAs<BuiltinType>()->getKind()) { - default: assert(0 && "getFloatingRank(): not a floating type"); + default: llvm_unreachable("getFloatingRank(): not a floating type"); + case BuiltinType::Half: return HalfRank; case BuiltinType::Float: return FloatRank; case BuiltinType::Double: return DoubleRank; case BuiltinType::LongDouble: return LongDoubleRank; @@ -3413,7 +3507,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, FloatingRank EltRank = getFloatingRank(Size); if (Domain->isComplexType()) { switch (EltRank) { - default: assert(0 && "getFloatingRank(): illegal value for rank"); + default: llvm_unreachable("getFloatingRank(): illegal value for rank"); case FloatRank: return FloatComplexTy; case DoubleRank: return DoubleComplexTy; case LongDoubleRank: return LongDoubleComplexTy; @@ -3422,7 +3516,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, assert(Domain->isRealFloatingType() && "Unknown domain!"); switch (EltRank) { - default: assert(0 && "getFloatingRank(): illegal value for rank"); + default: llvm_unreachable("getFloatingRank(): illegal value for rank"); case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; case LongDoubleRank: return LongDoubleTy; @@ -3454,16 +3548,16 @@ unsigned ASTContext::getIntegerRank(const Type *T) const { if (T->isSpecificBuiltinType(BuiltinType::WChar_S) || T->isSpecificBuiltinType(BuiltinType::WChar_U)) - T = getFromTargetType(Target.getWCharType()).getTypePtr(); + T = getFromTargetType(Target->getWCharType()).getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Char16)) - T = getFromTargetType(Target.getChar16Type()).getTypePtr(); + T = getFromTargetType(Target->getChar16Type()).getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Char32)) - T = getFromTargetType(Target.getChar32Type()).getTypePtr(); + T = getFromTargetType(Target->getChar32Type()).getTypePtr(); switch (cast<BuiltinType>(T)->getKind()) { - default: assert(0 && "getIntegerRank(): not a built-in integer"); + default: llvm_unreachable("getIntegerRank(): not a built-in integer"); case BuiltinType::Bool: return 1 + (getIntWidth(BoolTy) << 3); case BuiltinType::Char_S: @@ -3504,8 +3598,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { QualType FT = Field->getType(); - llvm::APSInt BitWidthAP = Field->getBitWidth()->EvaluateAsInt(*this); - uint64_t BitWidth = BitWidthAP.getZExtValue(); + uint64_t BitWidth = Field->getBitWidthValue(*this); uint64_t IntSize = getTypeSize(IntTy); // GCC extension compatibility: if the bit-field size is less than or equal // to the size of int, it gets promoted no matter what its type is. @@ -3653,82 +3746,6 @@ void ASTContext::setCFConstantStringType(QualType T) { CFConstantStringTypeDecl = Rec->getDecl(); } -// getNSConstantStringType - Return the type used for constant NSStrings. -QualType ASTContext::getNSConstantStringType() const { - if (!NSConstantStringTypeDecl) { - NSConstantStringTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, - &Idents.get("__builtin_NSString")); - NSConstantStringTypeDecl->startDefinition(); - - QualType FieldTypes[3]; - - // const int *isa; - FieldTypes[0] = getPointerType(IntTy.withConst()); - // const char *str; - FieldTypes[1] = getPointerType(CharTy.withConst()); - // unsigned int length; - FieldTypes[2] = UnsignedIntTy; - - // Create fields - for (unsigned i = 0; i < 3; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, NSConstantStringTypeDecl, - SourceLocation(), - SourceLocation(), 0, - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, - /*Mutable=*/false, - /*HasInit=*/false); - Field->setAccess(AS_public); - NSConstantStringTypeDecl->addDecl(Field); - } - - NSConstantStringTypeDecl->completeDefinition(); - } - - return getTagDeclType(NSConstantStringTypeDecl); -} - -void ASTContext::setNSConstantStringType(QualType T) { - const RecordType *Rec = T->getAs<RecordType>(); - assert(Rec && "Invalid NSConstantStringType"); - NSConstantStringTypeDecl = Rec->getDecl(); -} - -QualType ASTContext::getObjCFastEnumerationStateType() const { - if (!ObjCFastEnumerationStateTypeDecl) { - ObjCFastEnumerationStateTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, - &Idents.get("__objcFastEnumerationState")); - ObjCFastEnumerationStateTypeDecl->startDefinition(); - - QualType FieldTypes[] = { - UnsignedLongTy, - getPointerType(ObjCIdTypedefType), - getPointerType(UnsignedLongTy), - getConstantArrayType(UnsignedLongTy, - llvm::APInt(32, 5), ArrayType::Normal, 0) - }; - - for (size_t i = 0; i < 4; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, - ObjCFastEnumerationStateTypeDecl, - SourceLocation(), - SourceLocation(), 0, - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, - /*Mutable=*/false, - /*HasInit=*/false); - Field->setAccess(AS_public); - ObjCFastEnumerationStateTypeDecl->addDecl(Field); - } - - ObjCFastEnumerationStateTypeDecl->completeDefinition(); - } - - return getTagDeclType(ObjCFastEnumerationStateTypeDecl); -} - QualType ASTContext::getBlockDescriptorType() const { if (BlockDescriptorType) return getTagDeclType(BlockDescriptorType); @@ -3768,12 +3785,6 @@ QualType ASTContext::getBlockDescriptorType() const { return getTagDeclType(BlockDescriptorType); } -void ASTContext::setBlockDescriptorType(QualType T) { - const RecordType *Rec = T->getAs<RecordType>(); - assert(Rec && "Invalid BlockDescriptorType"); - BlockDescriptorType = Rec->getDecl(); -} - QualType ASTContext::getBlockDescriptorExtendedType() const { if (BlockDescriptorExtendedType) return getTagDeclType(BlockDescriptorExtendedType); @@ -3817,12 +3828,6 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { return getTagDeclType(BlockDescriptorExtendedType); } -void ASTContext::setBlockDescriptorExtendedType(QualType T) { - const RecordType *Rec = T->getAs<RecordType>(); - assert(Rec && "Invalid BlockDescriptorType"); - BlockDescriptorExtendedType = Rec->getDecl(); -} - bool ASTContext::BlockRequiresCopying(QualType Ty) const { if (Ty->isObjCRetainableType()) return true; @@ -3837,7 +3842,7 @@ bool ASTContext::BlockRequiresCopying(QualType Ty) const { } QualType -ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { +ASTContext::BuildByRefType(StringRef DeclName, QualType Ty) const { // type = struct __Block_byref_1_X { // void *__isa; // struct __Block_byref_1_X *__forwarding; @@ -3869,7 +3874,7 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { Ty }; - llvm::StringRef FieldNames[] = { + StringRef FieldNames[] = { "__isa", "__forwarding", "__flags", @@ -3897,10 +3902,15 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { return getPointerType(getTagDeclType(T)); } -void ASTContext::setObjCFastEnumerationStateType(QualType T) { - const RecordType *Rec = T->getAs<RecordType>(); - assert(Rec && "Invalid ObjCFAstEnumerationStateType"); - ObjCFastEnumerationStateTypeDecl = Rec->getDecl(); +TypedefDecl *ASTContext::getObjCInstanceTypeDecl() { + if (!ObjCInstanceTypeDecl) + ObjCInstanceTypeDecl = TypedefDecl::Create(*this, + getTranslationUnitDecl(), + SourceLocation(), + SourceLocation(), + &Idents.get("instancetype"), + getTrivialTypeSourceInfo(getObjCIdType())); + return ObjCInstanceTypeDecl; } // This returns true if a type has been typedefed to BOOL: @@ -3962,7 +3972,6 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { S += charUnitsToString(ParmOffset); // Block pointer and offset. S += "@?0"; - ParmOffset = PtrSize; // Argument types. ParmOffset = PtrSize; @@ -4044,7 +4053,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, // The first two arguments (self and _cmd) are pointers; account for // their size. CharUnits ParmOffset = 2 * PtrSize; - for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(), + for (ObjCMethodDecl::param_const_iterator PI = Decl->param_begin(), E = Decl->sel_param_end(); PI != E; ++PI) { QualType PType = (*PI)->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); @@ -4061,9 +4070,9 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, // Argument types. ParmOffset = 2 * PtrSize; - for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(), + for (ObjCMethodDecl::param_const_iterator PI = Decl->param_begin(), E = Decl->sel_param_end(); PI != E; ++PI) { - ParmVarDecl *PVDecl = *PI; + const ParmVarDecl *PVDecl = *PI; QualType PType = PVDecl->getOriginalType(); if (const ArrayType *AT = dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { @@ -4166,6 +4175,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, case ObjCPropertyDecl::Assign: break; case ObjCPropertyDecl::Copy: S += ",C"; break; case ObjCPropertyDecl::Retain: S += ",&"; break; + case ObjCPropertyDecl::Weak: S += ",W"; break; } } @@ -4225,7 +4235,7 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S, static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { switch (T->getAs<BuiltinType>()->getKind()) { - default: assert(0 && "Unhandled builtin type kind"); + default: llvm_unreachable("Unhandled builtin type kind"); case BuiltinType::Void: return 'v'; case BuiltinType::Bool: return 'B'; case BuiltinType::Char_U: @@ -4252,10 +4262,20 @@ static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { } } +static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { + EnumDecl *Enum = ET->getDecl(); + + // The encoding of an non-fixed enum type is always 'i', regardless of size. + if (!Enum->isFixed()) + return 'i'; + + // The encoding of a fixed enum type matches its fixed underlying type. + return ObjCEncodingForPrimitiveKind(C, Enum->getIntegerType()); +} + static void EncodeBitField(const ASTContext *Ctx, std::string& S, QualType T, const FieldDecl *FD) { - const Expr *E = FD->getBitWidth(); - assert(E && "bitfield width not there - getObjCEncodingForTypeImpl"); + assert(FD->isBitField() && "not a bitfield - getObjCEncodingForTypeImpl"); 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, @@ -4276,13 +4296,12 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, const RecordDecl *RD = FD->getParent(); const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD); S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex())); - if (T->isEnumeralType()) - S += 'i'; + if (const EnumType *ET = T->getAs<EnumType>()) + S += ObjCEncodingForEnumType(Ctx, ET); else S += ObjCEncodingForPrimitiveKind(Ctx, T); } - unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue(); - S += llvm::utostr(N); + S += llvm::utostr(FD->getBitWidthValue(*Ctx)); } // FIXME: Use SmallString for accumulating string. @@ -4342,7 +4361,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Another legacy compatibility encoding. Some ObjC qualifier and type // combinations need to be rearranged. // Rewrite "in const" from "nr" to "rn" - if (llvm::StringRef(S).endswith("nr")) + if (StringRef(S).endswith("nr")) S.replace(S.end()-2, S.end(), "rn"); } @@ -4423,7 +4442,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, = TemplateSpecializationType::PrintTemplateArgumentList( TemplateArgs.data(), TemplateArgs.size(), - (*this).PrintingPolicy); + (*this).getPrintingPolicy()); S += TemplateArgsStr; } @@ -4463,11 +4482,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - if (T->isEnumeralType()) { + if (const EnumType *ET = T->getAs<EnumType>()) { if (FD && FD->isBitField()) EncodeBitField(this, S, T, FD); else - S += 'i'; + S += ObjCEncodingForEnumType(this, ET); return; } @@ -4487,10 +4506,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, const IdentifierInfo *II = OI->getIdentifier(); S += II->getName(); S += '='; - llvm::SmallVector<ObjCIvarDecl*, 32> Ivars; + SmallVector<const ObjCIvarDecl*, 32> Ivars; DeepCollectObjCIvars(OI, true, Ivars); for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { - FieldDecl *Field = cast<FieldDecl>(Ivars[i]); + const FieldDecl *Field = cast<FieldDecl>(Ivars[i]); if (Field->isBitField()) getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); else @@ -4573,7 +4592,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - assert(0 && "@encode for type not implemented!"); + llvm_unreachable("@encode for type not implemented!"); } void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, @@ -4621,8 +4640,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (base->isEmpty()) continue; uint64_t offs = layout.getVBaseClassOffsetInBits(base); - FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), - std::make_pair(offs, base)); + if (FieldOrBaseOffsets.find(offs) == FieldOrBaseOffsets.end()) + FieldOrBaseOffsets.insert(FieldOrBaseOffsets.end(), + std::make_pair(offs, base)); } } @@ -4637,7 +4657,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, std::multimap<uint64_t, NamedDecl *>::iterator CurLayObj = FieldOrBaseOffsets.begin(); - if (CurLayObj != FieldOrBaseOffsets.end() && CurLayObj->first != 0) { + if ((CurLayObj != FieldOrBaseOffsets.end() && CurLayObj->first != 0) || + (CurLayObj == FieldOrBaseOffsets.end() && + CXXRec && CXXRec->isDynamicClass())) { assert(CXXRec && CXXRec->isDynamicClass() && "Offset 0 was empty but no VTable ?"); if (FD) { @@ -4695,7 +4717,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (field->isBitField()) { EncodeBitField(this, S, field->getType(), field); - CurOffs += field->getBitWidth()->EvaluateAsInt(*this).getZExtValue(); + CurOffs += field->getBitWidthValue(*this); } else { QualType qt = field->getType(); getLegacyIntegralTypeEncoding(qt); @@ -4731,20 +4753,48 @@ void ASTContext::setBuiltinVaListType(QualType T) { BuiltinVaListType = T; } -void ASTContext::setObjCIdType(QualType T) { - ObjCIdTypedefType = T; +TypedefDecl *ASTContext::getObjCIdDecl() const { + if (!ObjCIdDecl) { + QualType T = getObjCObjectType(ObjCBuiltinIdTy, 0, 0); + T = getObjCObjectPointerType(T); + TypeSourceInfo *IdInfo = getTrivialTypeSourceInfo(T); + ObjCIdDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), + getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Idents.get("id"), IdInfo); + } + + return ObjCIdDecl; } -void ASTContext::setObjCSelType(QualType T) { - ObjCSelTypedefType = T; +TypedefDecl *ASTContext::getObjCSelDecl() const { + if (!ObjCSelDecl) { + QualType SelT = getPointerType(ObjCBuiltinSelTy); + TypeSourceInfo *SelInfo = getTrivialTypeSourceInfo(SelT); + ObjCSelDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), + getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Idents.get("SEL"), SelInfo); + } + return ObjCSelDecl; } void ASTContext::setObjCProtoType(QualType QT) { ObjCProtoType = QT; } -void ASTContext::setObjCClassType(QualType T) { - ObjCClassTypedefType = T; +TypedefDecl *ASTContext::getObjCClassDecl() const { + if (!ObjCClassDecl) { + QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0); + T = getObjCObjectPointerType(T); + TypeSourceInfo *ClassInfo = getTrivialTypeSourceInfo(T); + ObjCClassDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), + getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Idents.get("Class"), ClassInfo); + } + + return ObjCClassDecl; } void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { @@ -4925,8 +4975,7 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const { case TargetInfo::UnsignedLongLong: return UnsignedLongLongTy; } - assert(false && "Unhandled TargetInfo::IntType value"); - return CanQualType(); + llvm_unreachable("Unhandled TargetInfo::IntType value"); } //===----------------------------------------------------------------------===// @@ -4937,7 +4986,7 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const { /// garbage collection attribute. /// Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const { - if (getLangOptions().getGCMode() == LangOptions::NonGC) + if (getLangOptions().getGC() == LangOptions::NonGC) return Qualifiers::GCNone; assert(getLangOptions().ObjC1); @@ -5261,7 +5310,7 @@ static void getIntersectionOfProtocols(ASTContext &Context, const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT, - llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) { + SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) { const ObjCObjectType* LHS = LHSOPT->getObjectType(); const ObjCObjectType* RHS = RHSOPT->getObjectType(); @@ -5287,8 +5336,7 @@ void getIntersectionOfProtocols(ASTContext &Context, for (unsigned i = 0; i < RHSNumProtocols; ++i) if (InheritedProtocolSet.count(RHSProtocols[i])) IntersectionOfProtocols.push_back(RHSProtocols[i]); - } - else { + } else { llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols; Context.CollectInheritedProtocols(RHS->getInterface(), RHSInheritedProtocols); @@ -5317,7 +5365,7 @@ QualType ASTContext::areCommonBaseCompatible( do { LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl)); if (canAssignObjCInterfaces(LHS, RHS)) { - llvm::SmallVector<ObjCProtocolDecl *, 8> Protocols; + SmallVector<ObjCProtocolDecl *, 8> Protocols; getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols); QualType Result = QualType(LHS, 0); @@ -5552,13 +5600,13 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult()) return QualType(); - // It's noreturn if either type is. - // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. - bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); - if (NoReturn != lbaseInfo.getNoReturn()) + // functypes which return are preferred over those that do not. + if (lbaseInfo.getNoReturn() && !rbaseInfo.getNoReturn()) allLTypes = false; - if (NoReturn != rbaseInfo.getNoReturn()) + else if (!lbaseInfo.getNoReturn() && rbaseInfo.getNoReturn()) allRTypes = false; + // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. + bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn); @@ -5579,8 +5627,12 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lproto->getTypeQuals() != rproto->getTypeQuals()) return QualType(); + if (LangOpts.ObjCAutoRefCount && + !FunctionTypesMatchOnNSConsumedAttrs(rproto, lproto)) + return QualType(); + // Check argument compatibility - llvm::SmallVector<QualType, 10> types; + SmallVector<QualType, 10> types; for (unsigned i = 0; i < lproto_nargs; i++) { QualType largtype = lproto->getArgType(i).getUnqualifiedType(); QualType rargtype = rproto->getArgType(i).getUnqualifiedType(); @@ -5603,6 +5655,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (getCanonicalType(argtype) != getCanonicalType(rargtype)) allRTypes = false; } + if (allLTypes) return lhs; if (allRTypes) return rhs; @@ -5756,22 +5809,19 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, #define NON_CANONICAL_TYPE(Class, Base) case Type::Class: #define DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" - assert(false && "Non-canonical and dependent types shouldn't get here"); - return QualType(); + llvm_unreachable("Non-canonical and dependent types shouldn't get here"); case Type::LValueReference: case Type::RValueReference: case Type::MemberPointer: - assert(false && "C++ should never be in mergeTypes"); - return QualType(); + llvm_unreachable("C++ should never be in mergeTypes"); case Type::ObjCInterface: case Type::IncompleteArray: case Type::VariableArray: case Type::FunctionProto: case Type::ExtVector: - assert(false && "Types are eliminated above"); - return QualType(); + llvm_unreachable("Types are eliminated above"); case Type::Pointer: { @@ -5809,6 +5859,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return RHS; return getBlockPointerType(ResultType); } + case Type::Atomic: + { + // Merge two pointer types, while trying to preserve typedef info + QualType LHSValue = LHS->getAs<AtomicType>()->getValueType(); + QualType RHSValue = RHS->getAs<AtomicType>()->getValueType(); + if (Unqualified) { + LHSValue = LHSValue.getUnqualifiedType(); + RHSValue = RHSValue.getUnqualifiedType(); + } + QualType ResultType = mergeTypes(LHSValue, RHSValue, false, + Unqualified); + if (ResultType.isNull()) return QualType(); + if (getCanonicalType(LHSValue) == getCanonicalType(ResultType)) + return LHS; + if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) + return RHS; + return getAtomicType(ResultType); + } case Type::ConstantArray: { const ConstantArrayType* LCAT = getAsConstantArrayType(LHS); @@ -5904,6 +5972,26 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return QualType(); } +bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs( + const FunctionProtoType *FromFunctionType, + const FunctionProtoType *ToFunctionType) { + if (FromFunctionType->hasAnyConsumedArgs() != + ToFunctionType->hasAnyConsumedArgs()) + return false; + FunctionProtoType::ExtProtoInfo FromEPI = + FromFunctionType->getExtProtoInfo(); + FunctionProtoType::ExtProtoInfo ToEPI = + ToFunctionType->getExtProtoInfo(); + if (FromEPI.ConsumedArguments && ToEPI.ConsumedArguments) + for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); + ArgIdx != NumArgs; ++ArgIdx) { + if (FromEPI.ConsumedArguments[ArgIdx] != + ToEPI.ConsumedArguments[ArgIdx]) + return false; + } + return true; +} + /// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and /// 'RHS' attributes and returns the merged version; including for function /// return types. @@ -6022,8 +6110,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) { case BuiltinType::Int128: return UnsignedInt128Ty; default: - assert(0 && "Unexpected signed integer type"); - return QualType(); + llvm_unreachable("Unexpected signed integer type"); } } @@ -6080,7 +6167,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, // Read the base type. switch (*Str++) { - default: assert(0 && "Unknown builtin type letter!"); + default: llvm_unreachable("Unknown builtin type letter!"); case 'v': assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers used with 'v'!"); @@ -6183,7 +6270,11 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(!RequiresICE && "Can't require complex ICE"); Type = Context.getComplexType(ElementType); break; - } + } + case 'Y' : { + Type = Context.getPointerDiffType(); + break; + } case 'P': Type = Context.getFILEType(); if (Type.isNull()) { @@ -6247,7 +6338,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id, unsigned *IntegerConstantArgs) const { const char *TypeStr = BuiltinInfo.GetTypeString(Id); - llvm::SmallVector<QualType, 8> ArgTypes; + SmallVector<QualType, 8> ArgTypes; bool RequiresICE = false; Error = GE_None; @@ -6405,7 +6496,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // Forward declarations aren't required. if (!FD->doesThisDeclarationHaveABody()) - return false; + return FD->doesDeclarationForceExternallyVisibleDefinition(); // Constructors and destructors are required. if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) @@ -6431,7 +6522,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; return true; } - + const VarDecl *VD = cast<VarDecl>(D); assert(VD->isFileVarDecl() && "Expected file scoped var"); @@ -6472,30 +6563,42 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { } MangleContext *ASTContext::createMangleContext() { - switch (Target.getCXXABI()) { + switch (Target->getCXXABI()) { case CXXABI_ARM: case CXXABI_Itanium: return createItaniumMangleContext(*this, getDiagnostics()); case CXXABI_Microsoft: return createMicrosoftMangleContext(*this, getDiagnostics()); } - assert(0 && "Unsupported ABI"); - return 0; + llvm_unreachable("Unsupported ABI"); } CXXABI::~CXXABI() {} size_t ASTContext::getSideTableAllocatedMemory() const { - size_t bytes = 0; - bytes += ASTRecordLayouts.getMemorySize(); - bytes += ObjCLayouts.getMemorySize(); - bytes += KeyFunctions.getMemorySize(); - bytes += ObjCImpls.getMemorySize(); - bytes += BlockVarCopyInits.getMemorySize(); - bytes += DeclAttrs.getMemorySize(); - bytes += InstantiatedFromStaticDataMember.getMemorySize(); - bytes += InstantiatedFromUsingDecl.getMemorySize(); - bytes += InstantiatedFromUsingShadowDecl.getMemorySize(); - bytes += InstantiatedFromUnnamedFieldDecl.getMemorySize(); - return bytes; + return ASTRecordLayouts.getMemorySize() + + llvm::capacity_in_bytes(ObjCLayouts) + + llvm::capacity_in_bytes(KeyFunctions) + + llvm::capacity_in_bytes(ObjCImpls) + + llvm::capacity_in_bytes(BlockVarCopyInits) + + llvm::capacity_in_bytes(DeclAttrs) + + llvm::capacity_in_bytes(InstantiatedFromStaticDataMember) + + llvm::capacity_in_bytes(InstantiatedFromUsingDecl) + + llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl) + + llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) + + llvm::capacity_in_bytes(OverriddenMethods) + + llvm::capacity_in_bytes(Types) + + llvm::capacity_in_bytes(VariableArrayTypes) + + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); +} + +void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { + ParamIndices[D] = index; +} + +unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const { + ParameterIndexTable::const_iterator I = ParamIndices.find(D); + assert(I != ParamIndices.end() && + "ParmIndices lacks entry set by ParmVarDecl"); + return I->second; } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 7c91b5c..07820dc 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -152,16 +152,16 @@ break; \ /// diagnostic message static std::string ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, - const Diagnostic::ArgumentValue *PrevArgs, + const DiagnosticsEngine::ArgumentValue *PrevArgs, unsigned NumPrevArgs, - llvm::SmallVectorImpl<intptr_t> &QualTypeVals) { + SmallVectorImpl<intptr_t> &QualTypeVals) { // FIXME: Playing with std::string is really slow. bool ForceAKA = false; QualType CanTy = Ty.getCanonicalType(); - std::string S = Ty.getAsString(Context.PrintingPolicy); - std::string CanS = CanTy.getAsString(Context.PrintingPolicy); + std::string S = Ty.getAsString(Context.getPrintingPolicy()); + std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); - for (llvm::SmallVectorImpl<intptr_t>::iterator I = QualTypeVals.begin(), + for (SmallVectorImpl<intptr_t>::iterator I = QualTypeVals.begin(), E = QualTypeVals.end(); I != E; ++I) { QualType CompareTy = QualType::getFromOpaquePtr(reinterpret_cast<void*>(*I)); @@ -170,10 +170,10 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, QualType CompareCanTy = CompareTy.getCanonicalType(); if (CompareCanTy == CanTy) continue; // Same canonical types - std::string CompareS = CompareTy.getAsString(Context.PrintingPolicy); + std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy()); if (CompareS != S) continue; // Original strings are different - std::string CompareCanS = CompareCanTy.getAsString(Context.PrintingPolicy); + std::string CompareCanS = CompareCanTy.getAsString(Context.getPrintingPolicy()); if (CompareCanS == CanS) continue; // No new info from canonical type @@ -186,7 +186,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, bool Repeated = false; for (unsigned i = 0; i != NumPrevArgs; ++i) { // TODO: Handle ak_declcontext case. - if (PrevArgs[i].first == Diagnostic::ak_qualtype) { + if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { void *Ptr = (void*)PrevArgs[i].second; QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); if (PrevTy == Ty) { @@ -205,7 +205,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, if (DesugaredTy == Ty) { DesugaredTy = Ty.getCanonicalType(); } - std::string akaStr = DesugaredTy.getAsString(Context.PrintingPolicy); + std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy()); if (akaStr != S) { S = "'" + S + "' (aka '" + akaStr + "')"; return S; @@ -218,25 +218,25 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, } void clang::FormatASTNodeDiagnosticArgument( - Diagnostic::ArgumentKind Kind, + DiagnosticsEngine::ArgumentKind Kind, intptr_t Val, const char *Modifier, unsigned ModLen, const char *Argument, unsigned ArgLen, - const Diagnostic::ArgumentValue *PrevArgs, + const DiagnosticsEngine::ArgumentValue *PrevArgs, unsigned NumPrevArgs, - llvm::SmallVectorImpl<char> &Output, + SmallVectorImpl<char> &Output, void *Cookie, - llvm::SmallVectorImpl<intptr_t> &QualTypeVals) { + SmallVectorImpl<intptr_t> &QualTypeVals) { ASTContext &Context = *static_cast<ASTContext*>(Cookie); std::string S; bool NeedQuotes = true; switch (Kind) { - default: assert(0 && "unknown ArgumentKind"); - case Diagnostic::ak_qualtype: { + default: llvm_unreachable("unknown ArgumentKind"); + case DiagnosticsEngine::ak_qualtype: { assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for QualType argument"); @@ -246,7 +246,7 @@ void clang::FormatASTNodeDiagnosticArgument( NeedQuotes = false; break; } - case Diagnostic::ak_declarationname: { + case DiagnosticsEngine::ak_declarationname: { DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); S = N.getAsString(); @@ -260,7 +260,7 @@ void clang::FormatASTNodeDiagnosticArgument( "Invalid modifier for DeclarationName argument"); break; } - case Diagnostic::ak_nameddecl: { + case DiagnosticsEngine::ak_nameddecl: { bool Qualified; if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) Qualified = true; @@ -269,18 +269,18 @@ void clang::FormatASTNodeDiagnosticArgument( "Invalid modifier for NamedDecl* argument"); Qualified = false; } - reinterpret_cast<NamedDecl*>(Val)-> - getNameForDiagnostic(S, Context.PrintingPolicy, Qualified); + const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val); + ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), Qualified); break; } - case Diagnostic::ak_nestednamespec: { + case DiagnosticsEngine::ak_nestednamespec: { llvm::raw_string_ostream OS(S); reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, - Context.PrintingPolicy); + Context.getPrintingPolicy()); NeedQuotes = false; break; } - case Diagnostic::ak_declcontext: { + case DiagnosticsEngine::ak_declcontext: { DeclContext *DC = reinterpret_cast<DeclContext *> (Val); assert(DC && "Should never have a null declaration context"); @@ -305,7 +305,7 @@ void clang::FormatASTNodeDiagnosticArgument( S += "function "; S += "'"; - ND->getNameForDiagnostic(S, Context.PrintingPolicy, true); + ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), true); S += "'"; } NeedQuotes = false; diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index f5e392f..af66b04 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -59,6 +59,7 @@ namespace { QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T); QualType VisitFunctionProtoType(const FunctionProtoType *T); // FIXME: UnresolvedUsingType + QualType VisitParenType(const ParenType *T); QualType VisitTypedefType(const TypedefType *T); QualType VisitTypeOfExprType(const TypeOfExprType *T); // FIXME: DependentTypeOfExprType @@ -83,16 +84,20 @@ namespace { bool ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, SourceLocation &Loc); + void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = 0); void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); - bool ImportDefinition(RecordDecl *From, RecordDecl *To); + bool ImportDefinition(RecordDecl *From, RecordDecl *To, + bool ForceImport = false); + bool ImportDefinition(EnumDecl *From, EnumDecl *To, + bool ForceImport = false); TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, - llvm::SmallVectorImpl<TemplateArgument> &ToArgs); + SmallVectorImpl<TemplateArgument> &ToArgs); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); @@ -805,12 +810,74 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; } - + + case Type::Atomic: { + if (!IsStructurallyEquivalent(Context, + cast<AtomicType>(T1)->getValueType(), + cast<AtomicType>(T2)->getValueType())) + return false; + break; + } + } // end switch return true; } +/// \brief Determine structural equivalence of two fields. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + FieldDecl *Field1, FieldDecl *Field2) { + RecordDecl *Owner2 = cast<RecordDecl>(Field2->getDeclContext()); + + if (!IsStructurallyEquivalent(Context, + Field1->getType(), Field2->getType())) { + Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent) + << Context.C2.getTypeDeclType(Owner2); + Context.Diag2(Field2->getLocation(), diag::note_odr_field) + << Field2->getDeclName() << Field2->getType(); + Context.Diag1(Field1->getLocation(), diag::note_odr_field) + << Field1->getDeclName() << Field1->getType(); + return false; + } + + if (Field1->isBitField() != Field2->isBitField()) { + Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent) + << Context.C2.getTypeDeclType(Owner2); + if (Field1->isBitField()) { + Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) + << Field1->getDeclName() << Field1->getType() + << Field1->getBitWidthValue(Context.C1); + Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field) + << Field2->getDeclName(); + } else { + Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) + << Field2->getDeclName() << Field2->getType() + << Field2->getBitWidthValue(Context.C2); + Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field) + << Field1->getDeclName(); + } + return false; + } + + if (Field1->isBitField()) { + // Make sure that the bit-fields are the same length. + unsigned Bits1 = Field1->getBitWidthValue(Context.C1); + unsigned Bits2 = Field2->getBitWidthValue(Context.C2); + + if (Bits1 != Bits2) { + Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent) + << Context.C2.getTypeDeclType(Owner2); + Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) + << Field2->getDeclName() << Field2->getType() << Bits2; + Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) + << Field1->getDeclName() << Field1->getType() << Bits1; + return false; + } + } + + return true; +} + /// \brief Determine structural equivalence of two records. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { @@ -928,61 +995,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } - if (!IsStructurallyEquivalent(Context, - Field1->getType(), Field2->getType())) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag2(Field2->getLocation(), diag::note_odr_field) - << Field2->getDeclName() << Field2->getType(); - Context.Diag1(Field1->getLocation(), diag::note_odr_field) - << Field1->getDeclName() << Field1->getType(); - return false; - } - - if (Field1->isBitField() != Field2->isBitField()) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - if (Field1->isBitField()) { - llvm::APSInt Bits; - Field1->getBitWidth()->isIntegerConstantExpr(Bits, Context.C1); - Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) - << Field1->getDeclName() << Field1->getType() - << Bits.toString(10, false); - Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field) - << Field2->getDeclName(); - } else { - llvm::APSInt Bits; - Field2->getBitWidth()->isIntegerConstantExpr(Bits, Context.C2); - Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) - << Field2->getDeclName() << Field2->getType() - << Bits.toString(10, false); - Context.Diag1(Field1->getLocation(), - diag::note_odr_not_bit_field) - << Field1->getDeclName(); - } - return false; - } - - if (Field1->isBitField()) { - // Make sure that the bit-fields are the same length. - llvm::APSInt Bits1, Bits2; - if (!Field1->getBitWidth()->isIntegerConstantExpr(Bits1, Context.C1)) - return false; - if (!Field2->getBitWidth()->isIntegerConstantExpr(Bits2, Context.C2)) - return false; - - if (!IsSameValue(Bits1, Bits2)) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); - Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) - << Field2->getDeclName() << Field2->getType() - << Bits2.toString(10, false); - Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) - << Field1->getDeclName() << Field1->getType() - << Bits1.toString(10, false); - return false; - } - } + if (!IsStructurallyEquivalent(Context, *Field1, *Field2)) + return false; } if (Field2 != Field2End) { @@ -1360,6 +1374,7 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { case BuiltinType::Long : return Importer.getToContext().LongTy; case BuiltinType::LongLong : return Importer.getToContext().LongLongTy; case BuiltinType::Int128 : return Importer.getToContext().Int128Ty; + case BuiltinType::Half: return Importer.getToContext().HalfTy; case BuiltinType::Float: return Importer.getToContext().FloatTy; case BuiltinType::Double: return Importer.getToContext().DoubleTy; case BuiltinType::LongDouble: return Importer.getToContext().LongDoubleTy; @@ -1518,7 +1533,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { return QualType(); // Import argument types - llvm::SmallVector<QualType, 4> ArgTypes; + SmallVector<QualType, 4> ArgTypes; for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), AEnd = T->arg_type_end(); A != AEnd; ++A) { @@ -1529,7 +1544,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { } // Import exception types - llvm::SmallVector<QualType, 4> ExceptionTypes; + SmallVector<QualType, 4> ExceptionTypes; for (FunctionProtoType::exception_iterator E = T->exception_begin(), EEnd = T->exception_end(); E != EEnd; ++E) { @@ -1546,6 +1561,14 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ArgTypes.size(), EPI); } +QualType ASTNodeImporter::VisitParenType(const ParenType *T) { + QualType ToInnerType = Importer.Import(T->getInnerType()); + if (ToInnerType.isNull()) + return QualType(); + + return Importer.getToContext().getParenType(ToInnerType); +} + QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { TypedefNameDecl *ToDecl = dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl())); @@ -1628,7 +1651,7 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType( if (ToTemplate.isNull()) return QualType(); - llvm::SmallVector<TemplateArgument, 2> ToTemplateArgs; + SmallVector<TemplateArgument, 2> ToTemplateArgs; if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToTemplateArgs)) return QualType(); @@ -1677,7 +1700,7 @@ QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) { if (ToBaseType.isNull()) return QualType(); - llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols; + SmallVector<ObjCProtocolDecl *, 4> Protocols; for (ObjCObjectType::qual_iterator P = T->qual_begin(), PEnd = T->qual_end(); P != PEnd; ++P) { @@ -1731,6 +1754,35 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC, return false; } +void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { + if (!FromD) + return; + + if (!ToD) { + ToD = Importer.Import(FromD); + if (!ToD) + return; + } + + if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) { + if (RecordDecl *ToRecord = cast_or_null<RecordDecl>(ToD)) { + if (FromRecord->getDefinition() && !ToRecord->getDefinition()) { + ImportDefinition(FromRecord, ToRecord); + } + } + return; + } + + if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) { + if (EnumDecl *ToEnum = cast_or_null<EnumDecl>(ToD)) { + if (FromEnum->getDefinition() && !ToEnum->getDefinition()) { + ImportDefinition(FromEnum, ToEnum); + } + } + return; + } +} + void ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To) { @@ -1761,16 +1813,13 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, To.setNamedTypeInfo(Importer.Import(FromTInfo)); return; } - assert(0 && "Unknown name kind."); + llvm_unreachable("Unknown name kind."); } } void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { if (Importer.isMinimalImport() && !ForceImport) { - if (DeclContext *ToDC = Importer.ImportContext(FromDC)) { - ToDC->setHasExternalLexicalStorage(); - ToDC->setHasExternalVisibleStorage(); - } + Importer.ImportContext(FromDC); return; } @@ -1781,8 +1830,9 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { Importer.Import(*From); } -bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) { - if (To->getDefinition()) +bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, + bool ForceImport) { + if (To->getDefinition() || To->isBeingDefined()) return false; To->startDefinition(); @@ -1791,7 +1841,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) { if (CXXRecordDecl *ToCXX = dyn_cast<CXXRecordDecl>(To)) { CXXRecordDecl *FromCXX = cast<CXXRecordDecl>(From); - llvm::SmallVector<CXXBaseSpecifier *, 4> Bases; + SmallVector<CXXBaseSpecifier *, 4> Bases; for (CXXRecordDecl::base_class_iterator Base1 = FromCXX->bases_begin(), FromBaseEnd = FromCXX->bases_end(); @@ -1804,7 +1854,10 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) { SourceLocation EllipsisLoc; if (Base1->isPackExpansion()) EllipsisLoc = Importer.Import(Base1->getEllipsisLoc()); - + + // Ensure that we have a definition for the base. + ImportDefinitionIfNeeded(Base1->getType()->getAsCXXRecordDecl()); + Bases.push_back( new (Importer.getToContext()) CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()), @@ -1818,14 +1871,39 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) { ToCXX->setBases(Bases.data(), Bases.size()); } - ImportDeclContext(From); + ImportDeclContext(From, ForceImport); To->completeDefinition(); return false; } +bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, + bool ForceImport) { + if (To->getDefinition() || To->isBeingDefined()) + return false; + + To->startDefinition(); + + QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(From)); + if (T.isNull()) + return true; + + QualType ToPromotionType = Importer.Import(From->getPromotionType()); + if (ToPromotionType.isNull()) + return true; + + ImportDeclContext(From, ForceImport); + + // FIXME: we might need to merge the number of positive or negative bits + // if the enumerator lists don't match. + To->completeDefinition(T, ToPromotionType, + From->getNumPositiveBits(), + From->getNumNegativeBits()); + return false; +} + TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( TemplateParameterList *Params) { - llvm::SmallVector<NamedDecl *, 4> ToParams; + SmallVector<NamedDecl *, 4> ToParams; ToParams.reserve(Params->size()); for (TemplateParameterList::iterator P = Params->begin(), PEnd = Params->end(); @@ -1892,7 +1970,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { return TemplateArgument(); case TemplateArgument::Pack: { - llvm::SmallVector<TemplateArgument, 2> ToPack; + SmallVector<TemplateArgument, 2> ToPack; ToPack.reserve(From.pack_size()); if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack)) return TemplateArgument(); @@ -1910,7 +1988,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, - llvm::SmallVectorImpl<TemplateArgument> &ToArgs) { + SmallVectorImpl<TemplateArgument> &ToArgs) { for (unsigned I = 0; I != NumFromArgs; ++I) { TemplateArgument To = ImportTemplateArgument(FromArgs[I]); if (To.isNull() && !FromArgs[I].isNull()) @@ -1969,20 +2047,20 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { else MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace(); } else { - llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Namespace)) + SmallVector<NamedDecl *, 4> ConflictingDecls; + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace)) continue; - if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(*Lookup.first)) { + if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(FoundDecls[I])) { MergeWithNamespace = FoundNS; ConflictingDecls.clear(); break; } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2029,21 +2107,21 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // seen a typedef with the same name (that we can merge with) or any // other entity by that name (which name lookup could conflict with). if (!DC->isFunctionOrMethod()) { - llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; + SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; if (TypedefNameDecl *FoundTypedef = - dyn_cast<TypedefNameDecl>(*Lookup.first)) { + dyn_cast<TypedefNameDecl>(FoundDecls[I])) { if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) return Importer.Imported(D, FoundTypedef); } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2065,15 +2143,16 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { SourceLocation StartL = Importer.Import(D->getLocStart()); TypedefNameDecl *ToTypedef; if (IsAlias) + ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, + StartL, Loc, + Name.getAsIdentifierInfo(), + TInfo); + else ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, StartL, Loc, Name.getAsIdentifierInfo(), TInfo); - else - ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, - StartL, Loc, - Name.getAsIdentifierInfo(), - TInfo); + ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToTypedef); @@ -2109,14 +2188,14 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // We may already have an enum of the same name; try to find and match it. if (!DC->isFunctionOrMethod() && SearchName) { - llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + SmallVector<NamedDecl *, 4> ConflictingDecls; + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(SearchName, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - Decl *Found = *Lookup.first; + Decl *Found = FoundDecls[I]; if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) { if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) Found = Tag->getDecl(); @@ -2127,7 +2206,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { return Importer.Imported(D, FoundEnum); } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2157,25 +2236,9 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { D2->setIntegerType(ToIntegerType); // Import the definition - if (D->isDefinition()) { - QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(D)); - if (T.isNull()) - return 0; + if (D->isCompleteDefinition() && ImportDefinition(D, D2)) + return 0; - QualType ToPromotionType = Importer.Import(D->getPromotionType()); - if (ToPromotionType.isNull()) - return 0; - - D2->startDefinition(); - ImportDeclContext(D); - - // FIXME: we might need to merge the number of positive or negative bits - // if the enumerator lists don't match. - D2->completeDefinition(T, ToPromotionType, - D->getNumPositiveBits(), - D->getNumNegativeBits()); - } - return D2; } @@ -2211,14 +2274,14 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // We may already have a record of the same name; try to find and match it. RecordDecl *AdoptDecl = 0; if (!DC->isFunctionOrMethod() && SearchName) { - llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + SmallVector<NamedDecl *, 4> ConflictingDecls; + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(SearchName, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - Decl *Found = *Lookup.first; + Decl *Found = FoundDecls[I]; if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) { if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) Found = Tag->getDecl(); @@ -2226,7 +2289,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) { if (RecordDecl *FoundDef = FoundRecord->getDefinition()) { - if (!D->isDefinition() || IsStructuralMatch(D, FoundDef)) { + if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) { // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. @@ -2241,7 +2304,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2274,7 +2337,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Importer.Imported(D, D2); - if (D->isDefinition() && ImportDefinition(D, D2)) + if (D->isCompleteDefinition() && ImportDefinition(D, D2)) return 0; return D2; @@ -2295,15 +2358,15 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { // Determine whether there are any other declarations with the same name and // in the same context. if (!LexicalDC->isFunctionOrMethod()) { - llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; + SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2341,15 +2404,15 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. if (!LexicalDC->isFunctionOrMethod()) { - llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; + SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(*Lookup.first)) { + if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) { if (isExternalLinkage(FoundFunction->getLinkage()) && isExternalLinkage(D->getLinkage())) { if (Importer.IsStructurallyEquivalent(D->getType(), @@ -2374,7 +2437,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2396,7 +2459,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return 0; // Import the function parameters. - llvm::SmallVector<ParmVarDecl *, 8> Parameters; + SmallVector<ParmVarDecl *, 8> Parameters; for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); P != PEnd; ++P) { ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(*P)); @@ -2416,7 +2479,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { NameInfo, T, TInfo, FromConstructor->isExplicit(), D->isInlineSpecified(), - D->isImplicit()); + D->isImplicit(), + D->isConstexpr()); } else if (isa<CXXDestructorDecl>(D)) { ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), @@ -2432,6 +2496,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { NameInfo, T, TInfo, D->isInlineSpecified(), FromConversion->isExplicit(), + D->isConstexpr(), Importer.Import(D->getLocEnd())); } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { ToFunction = CXXMethodDecl::Create(Importer.getToContext(), @@ -2441,6 +2506,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { Method->isStatic(), Method->getStorageClassAsWritten(), Method->isInlineSpecified(), + D->isConstexpr(), Importer.Import(D->getLocEnd())); } else { ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, @@ -2448,7 +2514,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { NameInfo, T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), - D->hasWrittenPrototype()); + D->hasWrittenPrototype(), + D->isConstexpr()); } // Import the qualifier, if any. @@ -2465,7 +2532,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { Parameters[I]->setOwningFunction(ToFunction); ToFunction->addDecl(Parameters[I]); } - ToFunction->setParams(Parameters.data(), Parameters.size()); + ToFunction->setParams(Parameters); // FIXME: Other bits to merge? @@ -2499,6 +2566,25 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) return 0; + // Determine whether we've already imported this field. + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) { + if (Importer.IsStructurallyEquivalent(D->getType(), + FoundField->getType())) { + Importer.Imported(D, FoundField); + return FoundField; + } + + Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) + << Name << D->getType() << FoundField->getType(); + Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) + << FoundField->getType(); + return 0; + } + } + // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) @@ -2531,6 +2617,26 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) return 0; + // Determine whether we've already imported this field. + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (IndirectFieldDecl *FoundField + = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { + if (Importer.IsStructurallyEquivalent(D->getType(), + FoundField->getType())) { + Importer.Imported(D, FoundField); + return FoundField; + } + + Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) + << Name << D->getType() << FoundField->getType(); + Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) + << FoundField->getType(); + return 0; + } + } + // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) @@ -2568,10 +2674,10 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { return 0; // Determine whether we've already imported this ivar - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(*Lookup.first)) { + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { Importer.Imported(D, FoundIvar); @@ -2621,15 +2727,15 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // in the same context as the variable we're importing. if (D->isFileVarDecl()) { VarDecl *MergeWithVar = 0; - llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; + SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - if (VarDecl *FoundVar = dyn_cast<VarDecl>(*Lookup.first)) { + if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) { // We have found a variable that we may need to merge with. Check it. if (isExternalLinkage(FoundVar->getLinkage()) && isExternalLinkage(D->getLinkage())) { @@ -2668,7 +2774,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { } } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (MergeWithVar) { @@ -2794,10 +2900,10 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) return 0; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(*Lookup.first)) { + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecls[I])) { if (FoundMethod->isInstanceMethod() != D->isInstanceMethod()) continue; @@ -2872,6 +2978,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { D->isInstanceMethod(), D->isVariadic(), D->isSynthesized(), + D->isImplicit(), D->isDefined(), D->getImplementationControl(), D->hasRelatedResultType()); @@ -2880,7 +2987,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // deal with implicit parameters. // Import the parameters - llvm::SmallVector<ParmVarDecl *, 5> ToParams; + SmallVector<ParmVarDecl *, 5> ToParams; for (ObjCMethodDecl::param_iterator FromP = D->param_begin(), FromPEnd = D->param_end(); FromP != FromPEnd; @@ -2897,9 +3004,9 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { ToParams[I]->setOwningFunction(ToMethod); ToMethod->addDecl(ToParams[I]); } - ToMethod->setMethodParams(Importer.getToContext(), - ToParams.data(), ToParams.size(), - ToParams.size()); + SmallVector<SourceLocation, 12> SelLocs; + D->getSelectorLocs(SelLocs); + ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs); ToMethod->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToMethod); @@ -2926,21 +3033,18 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { ObjCCategoryDecl *ToCategory = MergeWithCategory; if (!ToCategory) { ToCategory = ObjCCategoryDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getAtLoc()), + Importer.Import(D->getAtStartLoc()), Loc, Importer.Import(D->getCategoryNameLoc()), - Name.getAsIdentifierInfo()); + Name.getAsIdentifierInfo(), + ToInterface); ToCategory->setLexicalDeclContext(LexicalDC); LexicalDC->addDecl(ToCategory); Importer.Imported(D, ToCategory); - // Link this category into its class's category list. - ToCategory->setClassInterface(ToInterface); - ToCategory->insertNextClassCategory(); - // Import protocols - llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols; - llvm::SmallVector<SourceLocation, 4> ProtocolLocs; + SmallVector<ObjCProtocolDecl *, 4> Protocols; + SmallVector<SourceLocation, 4> ProtocolLocs; ObjCCategoryDecl::protocol_loc_iterator FromProtoLoc = D->protocol_loc_begin(); for (ObjCCategoryDecl::protocol_iterator FromProto = D->protocol_begin(), @@ -2989,21 +3093,22 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { return 0; ObjCProtocolDecl *MergeWithProtocol = 0; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) continue; - if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(*Lookup.first))) + if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecls[I]))) break; } ObjCProtocolDecl *ToProto = MergeWithProtocol; if (!ToProto || ToProto->isForwardDecl()) { if (!ToProto) { - ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo()); + ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, + Name.getAsIdentifierInfo(), Loc, + Importer.Import(D->getAtStartLoc())); ToProto->setForwardDecl(D->isForwardDecl()); ToProto->setLexicalDeclContext(LexicalDC); LexicalDC->addDecl(ToProto); @@ -3011,8 +3116,8 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { Importer.Imported(D, ToProto); // Import protocols - llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols; - llvm::SmallVector<SourceLocation, 4> ProtocolLocs; + SmallVector<ObjCProtocolDecl *, 4> Protocols; + SmallVector<SourceLocation, 4> ProtocolLocs; ObjCProtocolDecl::protocol_loc_iterator FromProtoLoc = D->protocol_loc_begin(); for (ObjCProtocolDecl::protocol_iterator FromProto = D->protocol_begin(), @@ -3049,23 +3154,22 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { return 0; ObjCInterfaceDecl *MergeWithIface = 0; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; - if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(*Lookup.first))) + if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecls[I]))) break; } ObjCInterfaceDecl *ToIface = MergeWithIface; if (!ToIface || ToIface->isForwardDecl()) { if (!ToIface) { - ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), - DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getClassLoc()), + ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getAtStartLoc()), + Name.getAsIdentifierInfo(), Loc, D->isForwardDecl(), D->isImplicitInterfaceDecl()); ToIface->setForwardDecl(D->isForwardDecl()); @@ -3085,8 +3189,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { } // Import protocols - llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols; - llvm::SmallVector<SourceLocation, 4> ProtocolLocs; + SmallVector<ObjCProtocolDecl *, 4> Protocols; + SmallVector<SourceLocation, 4> ProtocolLocs; ObjCInterfaceDecl::protocol_loc_iterator FromProtoLoc = D->protocol_loc_begin(); @@ -3175,9 +3279,10 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { return 0; ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocation()), Importer.Import(D->getIdentifier()), - Category->getClassInterface()); + Category->getClassInterface(), + Importer.Import(D->getLocation()), + Importer.Import(D->getAtStartLoc())); DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { @@ -3219,8 +3324,9 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { // now. Impl = ObjCImplementationDecl::Create(Importer.getToContext(), Importer.ImportContext(D->getDeclContext()), + Iface, Super, Importer.Import(D->getLocation()), - Iface, Super); + Importer.Import(D->getAtStartLoc())); if (D->getDeclContext() != D->getLexicalDeclContext()) { DeclContext *LexicalDC @@ -3279,11 +3385,11 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { return 0; // Check whether we have already imported this property. - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCPropertyDecl *FoundProp - = dyn_cast<ObjCPropertyDecl>(*Lookup.first)) { + = dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) { // Check property types. if (!Importer.IsStructurallyEquivalent(D->getType(), FoundProp->getType())) { @@ -3430,8 +3536,8 @@ ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols; - llvm::SmallVector<SourceLocation, 4> Locations; + SmallVector<ObjCProtocolDecl *, 4> Protocols; + SmallVector<SourceLocation, 4> Locations; ObjCForwardProtocolDecl::protocol_loc_iterator FromProtoLoc = D->protocol_loc_begin(); for (ObjCForwardProtocolDecl::protocol_iterator FromProto @@ -3472,25 +3578,14 @@ Decl *ASTNodeImporter::VisitObjCClassDecl(ObjCClassDecl *D) { // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - - llvm::SmallVector<ObjCInterfaceDecl *, 4> Interfaces; - llvm::SmallVector<SourceLocation, 4> Locations; - for (ObjCClassDecl::iterator From = D->begin(), FromEnd = D->end(); - From != FromEnd; ++From) { - ObjCInterfaceDecl *ToIface - = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface())); - if (!ToIface) - continue; - - Interfaces.push_back(ToIface); - Locations.push_back(Importer.Import(From->getLocation())); - } - + ObjCClassDecl::ObjCClassRef *From = D->getForwardDecl(); + ObjCInterfaceDecl *ToIface + = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface())); ObjCClassDecl *ToClass = ObjCClassDecl::Create(Importer.getToContext(), DC, - Loc, - Interfaces.data(), - Locations.data(), - Interfaces.size()); + Loc, + ToIface, + Importer.Import(From->getLocation())); + ToClass->setLexicalDeclContext(LexicalDC); LexicalDC->addDecl(ToClass); Importer.Imported(D, ToClass); @@ -3594,14 +3689,14 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { - llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + SmallVector<NamedDecl *, 4> ConflictingDecls; + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; - Decl *Found = *Lookup.first; + Decl *Found = FoundDecls[I]; if (ClassTemplateDecl *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found)) { if (IsStructuralMatch(D, FoundTemplate)) { @@ -3614,7 +3709,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { } } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -3660,7 +3755,8 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { Importer.Imported(D, D2); Importer.Imported(DTemplated, D2Templated); - if (DTemplated->isDefinition() && !D2Templated->isDefinition()) { + if (DTemplated->isCompleteDefinition() && + !D2Templated->isCompleteDefinition()) { // FIXME: Import definition! } @@ -3704,7 +3800,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( SourceLocation IdLoc = Importer.Import(D->getLocation()); // Import template arguments. - llvm::SmallVector<TemplateArgument, 2> TemplateArgs; + SmallVector<TemplateArgument, 2> TemplateArgs; if (ImportTemplateArguments(D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) @@ -3722,7 +3818,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // FIXME: Check for specialization vs. instantiation errors. if (RecordDecl *FoundDef = D2->getDefinition()) { - if (!D->isDefinition() || IsStructuralMatch(D, FoundDef)) { + if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) { // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. @@ -3752,7 +3848,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( } Importer.Imported(D, D2); - if (D->isDefinition() && ImportDefinition(D, D2)) + if (D->isCompleteDefinition() && ImportDefinition(D, D2)) return 0; return D2; @@ -3792,14 +3888,17 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) return 0; - - return DeclRefExpr::Create(Importer.getToContext(), - Importer.Import(E->getQualifierLoc()), - ToD, - Importer.Import(E->getLocation()), - T, E->getValueKind(), - FoundD, - /*FIXME:TemplateArgs=*/0); + + DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), + Importer.Import(E->getQualifierLoc()), + ToD, + Importer.Import(E->getLocation()), + T, E->getValueKind(), + FoundD, + /*FIXME:TemplateArgs=*/0); + if (E->hadMultipleCandidates()) + DRE->setHadMultipleCandidates(true); + return DRE; } Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { @@ -3817,8 +3916,8 @@ Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { if (T.isNull()) return 0; - return new (Importer.getToContext()) CharacterLiteral(E->getValue(), - E->isWide(), T, + return new (Importer.getToContext()) CharacterLiteral(E->getValue(), + E->getKind(), T, Importer.Import(E->getLocation())); } @@ -4024,13 +4123,17 @@ Decl *ASTImporter::Import(Decl *FromD) { if (!FromD) return 0; + ASTNodeImporter Importer(*this); + // Check whether we've already imported this declaration. llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD); - if (Pos != ImportedDecls.end()) - return Pos->second; + if (Pos != ImportedDecls.end()) { + Decl *ToD = Pos->second; + Importer.ImportDefinitionIfNeeded(FromD, ToD); + return ToD; + } // Import the type - ASTNodeImporter Importer(*this); Decl *ToD = Importer.Visit(FromD); if (!ToD) return 0; @@ -4045,7 +4148,7 @@ Decl *ASTImporter::Import(Decl *FromD) { } else if (TypedefNameDecl *FromTypedef = dyn_cast<TypedefNameDecl>(FromD)) { // When we've finished transforming a typedef, see whether it was the // typedef for an anonymous tag. - for (llvm::SmallVector<TagDecl *, 4>::iterator + for (SmallVector<TagDecl *, 4>::iterator FromTag = AnonTagsWithPendingTypedefs.begin(), FromTagEnd = AnonTagsWithPendingTypedefs.end(); FromTag != FromTagEnd; ++FromTag) { @@ -4252,7 +4355,7 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) { std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc); SourceManager &ToSM = ToContext.getSourceManager(); return ToSM.getLocForStartOfFile(Import(Decomposed.first)) - .getFileLocWithOffset(Decomposed.second); + .getLocWithOffset(Decomposed.second); } SourceRange ASTImporter::Import(SourceRange FromRange) { @@ -4306,6 +4409,23 @@ void ASTImporter::ImportDefinition(Decl *From) { if (DeclContext *FromDC = cast<DeclContext>(From)) { ASTNodeImporter Importer(*this); + + if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(To)) { + if (!ToRecord->getDefinition()) { + Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord, + /*ForceImport=*/true); + return; + } + } + + if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(To)) { + if (!ToEnum->getDefinition()) { + Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum, + /*ForceImport=*/true); + return; + } + } + Importer.ImportDeclContext(FromDC, true); } } @@ -4378,7 +4498,7 @@ Selector ASTImporter::Import(Selector FromSel) { if (FromSel.isNull()) return Selector(); - llvm::SmallVector<IdentifierInfo *, 4> Idents; + SmallVector<IdentifierInfo *, 4> Idents; Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0))); for (unsigned I = 1, N = FromSel.getNumArgs(); I < N; ++I) Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(I))); diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index 9ffe1f8..f29bfd1 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -119,7 +119,7 @@ bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, void *OpaqueData, bool AllowShortCircuit) const { - llvm::SmallVector<const CXXRecordDecl*, 8> Queue; + SmallVector<const CXXRecordDecl*, 8> Queue; const CXXRecordDecl *Record = this; bool AllMatches = true; @@ -425,7 +425,7 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, void OverridingMethods::add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding) { - llvm::SmallVector<UniqueVirtualMethod, 4> &SubobjectOverrides + SmallVector<UniqueVirtualMethod, 4> &SubobjectOverrides = Overrides[OverriddenSubobject]; if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(), Overriding) == SubobjectOverrides.end()) @@ -556,7 +556,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, // overrides. typedef std::pair<CXXMethodDecl::method_iterator, CXXMethodDecl::method_iterator> OverriddenMethods; - llvm::SmallVector<OverriddenMethods, 4> Stack; + SmallVector<OverriddenMethods, 4> Stack; Stack.push_back(std::make_pair(CanonM->begin_overridden_methods(), CanonM->end_overridden_methods())); while (!Stack.empty()) { @@ -623,11 +623,11 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { SOEnd = OM->second.end(); SO != SOEnd; ++SO) { - llvm::SmallVector<UniqueVirtualMethod, 4> &Overriding = SO->second; + SmallVector<UniqueVirtualMethod, 4> &Overriding = SO->second; if (Overriding.size() < 2) continue; - for (llvm::SmallVector<UniqueVirtualMethod, 4>::iterator + for (SmallVector<UniqueVirtualMethod, 4>::iterator Pos = Overriding.begin(), PosEnd = Overriding.end(); Pos != PosEnd; /* increment in loop */) { @@ -642,7 +642,7 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { // in a base class subobject that hides the virtual base class // subobject. bool Hidden = false; - for (llvm::SmallVector<UniqueVirtualMethod, 4>::iterator + for (SmallVector<UniqueVirtualMethod, 4>::iterator OP = Overriding.begin(), OPEnd = Overriding.end(); OP != OPEnd && !Hidden; ++OP) { diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 4c323da..95d52cb 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -28,6 +28,8 @@ #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" +#include <algorithm> + using namespace clang; //===----------------------------------------------------------------------===// @@ -51,7 +53,7 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) { // If we're on Mac OS X, an 'availability' for Mac OS X attribute // implies visibility(default). - if (D->getASTContext().Target.getTriple().isOSDarwin()) { + if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) { for (specific_attr_iterator<AvailabilityAttr> A = D->specific_attr_begin<AvailabilityAttr>(), AEnd = D->specific_attr_end<AvailabilityAttr>(); @@ -818,7 +820,7 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { if (Ctx->isFunctionOrMethod()) return getNameAsString(); - typedef llvm::SmallVector<const DeclContext *, 8> ContextsTy; + typedef SmallVector<const DeclContext *, 8> ContextsTy; ContextsTy Contexts; // Collect contexts. @@ -845,18 +847,18 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { if (ND->isAnonymousNamespace()) OS << "<anonymous namespace>"; else - OS << ND; + OS << *ND; } else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) { if (!RD->getIdentifier()) OS << "<anonymous " << RD->getKindName() << '>'; else - OS << RD; + OS << *RD; } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { const FunctionProtoType *FT = 0; if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>()); - OS << FD << '('; + OS << *FD << '('; if (FT) { unsigned NumParams = FD->getNumParams(); for (unsigned i = 0; i < NumParams; ++i) { @@ -875,13 +877,13 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { } OS << ')'; } else { - OS << cast<NamedDecl>(*I); + OS << *cast<NamedDecl>(*I); } OS << "::"; } if (getDeclName()) - OS << this; + OS << *this; else OS << "<anonymous>"; @@ -1003,8 +1005,7 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; - } - else { + } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { @@ -1120,15 +1121,16 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { switch (SC) { - case SC_None: break; - case SC_Auto: return "auto"; break; - case SC_Extern: return "extern"; break; - case SC_PrivateExtern: return "__private_extern__"; break; - case SC_Register: return "register"; break; - case SC_Static: return "static"; break; + case SC_None: break; + case SC_Auto: return "auto"; + case SC_Extern: return "extern"; + case SC_OpenCLWorkGroupLocal: return "<<work-group-local>>"; + case SC_PrivateExtern: return "__private_extern__"; + case SC_Register: return "register"; + case SC_Static: return "static"; } - assert(0 && "Invalid storage class"); + llvm_unreachable("Invalid storage class"); return 0; } @@ -1388,6 +1390,16 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, S, SCAsWritten, DefArg); } +SourceRange ParmVarDecl::getSourceRange() const { + if (!hasInheritedDefaultArg()) { + SourceRange ArgRange = getDefaultArgRange(); + if (ArgRange.isValid()) + return SourceRange(getOuterLocStart(), ArgRange.getEnd()); + } + + return DeclaratorDecl::getSourceRange(); +} + Expr *ParmVarDecl::getDefaultArg() { assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); assert(!hasUninstantiatedDefaultArg() && @@ -1429,6 +1441,15 @@ bool ParmVarDecl::isParameterPack() const { return isa<PackExpansionType>(getType()); } +void ParmVarDecl::setParameterIndexLarge(unsigned parameterIndex) { + getASTContext().setParameterIndex(this, parameterIndex); + ParmVarDeclBits.ParameterIndex = ParameterIndexSentinel; +} + +unsigned ParmVarDecl::getParameterIndexLarge() const { + return getASTContext().getParameterIndex(this); +} + //===----------------------------------------------------------------------===// // FunctionDecl Implementation //===----------------------------------------------------------------------===// @@ -1678,20 +1699,14 @@ unsigned FunctionDecl::getNumParams() const { } void FunctionDecl::setParams(ASTContext &C, - ParmVarDecl **NewParamInfo, unsigned NumParams) { + llvm::ArrayRef<ParmVarDecl *> NewParamInfo) { assert(ParamInfo == 0 && "Already has param info!"); - assert(NumParams == getNumParams() && "Parameter count mismatch!"); + assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!"); // Zero params -> null pointer. - if (NumParams) { - void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); - ParamInfo = new (Mem) ParmVarDecl*[NumParams]; - memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); - - // Update source range. The check below allows us to set EndRangeLoc before - // setting the parameters. - if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation()) - EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd(); + if (!NewParamInfo.empty()) { + ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()]; + std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo); } } @@ -1762,6 +1777,33 @@ bool FunctionDecl::isInlined() const { return false; } +/// \brief For a function declaration in C or C++, determine whether this +/// declaration causes the definition to be externally visible. +/// +/// Determines whether this is the first non-inline redeclaration of an inline +/// function in a language where "inline" does not normally require an +/// externally visible definition. +bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { + assert(!doesThisDeclarationHaveABody() && + "Must have a declaration without a body."); + + ASTContext &Context = getASTContext(); + + // In C99 mode, a function may have an inline definition (causing it to + // be deferred) then redeclared later. As a special case, "extern inline" + // is not required to produce an external symbol. + if (Context.getLangOptions().GNUInline || !Context.getLangOptions().C99 || + Context.getLangOptions().CPlusPlus) + return false; + if (getLinkage() != ExternalLinkage || isInlineSpecified()) + return false; + const FunctionDecl *Definition = 0; + if (hasBody(Definition)) + return Definition->isInlined() && + Definition->isInlineDefinitionExternallyVisible(); + return false; +} + /// \brief For an inline function definition in C or C++, determine whether the /// definition will be externally visible. /// @@ -1814,7 +1856,12 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // Only consider file-scope declarations in this test. if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) continue; - + + // Only consider explicit declarations; the presence of a builtin for a + // libcall shouldn't affect whether a definition is externally visible. + if (Redecl->isImplicit()) + continue; + if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern) return true; // Not an inline definition } @@ -1857,8 +1904,7 @@ FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { <DependentFunctionTemplateSpecializationInfo*>()) return TK_DependentFunctionTemplateSpecialization; - assert(false && "Did we miss a TemplateOrSpecialization type?"); - return TK_NonTemplate; + llvm_unreachable("Did we miss a TemplateOrSpecialization type?"); } FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { @@ -1890,13 +1936,17 @@ bool FunctionDecl::isImplicitlyInstantiable() const { switch (getTemplateSpecializationKind()) { case TSK_Undeclared: - case TSK_ExplicitSpecialization: case TSK_ExplicitInstantiationDefinition: return false; case TSK_ImplicitInstantiation: return true; + // It is possible to instantiate TSK_ExplicitSpecialization kind + // if the FunctionDecl has a class scope specialization pattern. + case TSK_ExplicitSpecialization: + return getClassScopeSpecializationPattern() != 0; + case TSK_ExplicitInstantiationDeclaration: // Handled below. break; @@ -1919,6 +1969,10 @@ bool FunctionDecl::isImplicitlyInstantiable() const { } FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { + // Handle class scope explicit specialization special case. + if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return getClassScopeSpecializationPattern(); + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of @@ -1944,6 +1998,10 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { return 0; } +FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { + return getASTContext().getClassScopeSpecializationPattern(this); +} + const TemplateArgumentList * FunctionDecl::getTemplateSpecializationArgs() const { if (FunctionTemplateSpecializationInfo *Info @@ -1954,7 +2012,7 @@ FunctionDecl::getTemplateSpecializationArgs() const { return 0; } -const TemplateArgumentListInfo * +const ASTTemplateArgumentListInfo * FunctionDecl::getTemplateSpecializationArgsAsWritten() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization @@ -2069,7 +2127,7 @@ FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, MSInfo->getPointOfInstantiation().isInvalid()) MSInfo->setPointOfInstantiation(PointOfInstantiation); } else - assert(false && "Function cannot have a template specialization kind"); + llvm_unreachable("Function cannot have a template specialization kind"); } SourceLocation FunctionDecl::getPointOfInstantiation() const { @@ -2134,6 +2192,12 @@ bool FieldDecl::isAnonymousStructOrUnion() const { return false; } +unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { + assert(isBitField() && "not a bitfield"); + Expr *BitWidth = InitializerOrBitWidth.getPointer(); + return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue(); +} + unsigned FieldDecl::getFieldIndex() const { if (CachedFieldIndex) return CachedFieldIndex - 1; @@ -2165,8 +2229,8 @@ unsigned FieldDecl::getFieldIndex() const { } SourceRange FieldDecl::getSourceRange() const { - if (isBitField()) - return SourceRange(getInnerLocStart(), getBitWidth()->getLocEnd()); + if (const Expr *E = InitializerOrBitWidth.getPointer()) + return SourceRange(getInnerLocStart(), E->getLocEnd()); return DeclaratorDecl::getSourceRange(); } @@ -2218,22 +2282,22 @@ void TagDecl::completeDefinition() { cast<CXXRecordDecl>(this)->hasDefinition()) && "definition completed but not started"); - IsDefinition = true; + IsCompleteDefinition = true; IsBeingDefined = false; if (ASTMutationListener *L = getASTMutationListener()) L->CompletedTagDefinition(this); } -TagDecl* TagDecl::getDefinition() const { - if (isDefinition()) +TagDecl *TagDecl::getDefinition() const { + if (isCompleteDefinition()) return const_cast<TagDecl *>(this); if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); R != REnd; ++R) - if (R->isDefinition()) + if (R->isCompleteDefinition()) return *R; return 0; @@ -2246,8 +2310,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; - } - else { + } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { @@ -2296,7 +2359,7 @@ void EnumDecl::completeDefinition(QualType NewType, QualType NewPromotionType, unsigned NumPositiveBits, unsigned NumNegativeBits) { - assert(!isDefinition() && "Cannot redefine enums!"); + assert(!isCompleteDefinition() && "Cannot redefine enums!"); if (!IntegerType) IntegerType = NewType.getTypePtr(); PromotionType = NewPromotionType; @@ -2349,7 +2412,7 @@ RecordDecl::field_iterator RecordDecl::field_begin() const { /// completeDefinition - Notes that the definition of this type is now /// complete. void RecordDecl::completeDefinition() { - assert(!isDefinition() && "Cannot redefine record!"); + assert(!isCompleteDefinition() && "Cannot redefine record!"); TagDecl::completeDefinition(); } @@ -2360,7 +2423,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { // Notify that we have a RecordDecl doing some initialization. ExternalASTSource::Deserializing TheFields(Source); - llvm::SmallVector<Decl*, 64> Decls; + SmallVector<Decl*, 64> Decls; LoadedFieldsFromExternalStorage = true; switch (Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls)) { case ELR_Success: @@ -2380,23 +2443,22 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { if (Decls.empty()) return; - llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls); + llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, + /*FieldsAlreadyLoaded=*/false); } //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// -void BlockDecl::setParams(ParmVarDecl **NewParamInfo, - unsigned NParms) { +void BlockDecl::setParams(llvm::ArrayRef<ParmVarDecl *> NewParamInfo) { assert(ParamInfo == 0 && "Already has param info!"); // Zero params -> null pointer. - if (NParms) { - NumParams = NParms; - void *Mem = getASTContext().Allocate(sizeof(ParmVarDecl*)*NumParams); - ParamInfo = new (Mem) ParmVarDecl*[NumParams]; - memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); + if (!NewParamInfo.empty()) { + NumParams = NewParamInfo.size(); + ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()]; + std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo); } } @@ -2481,10 +2543,12 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, QualType T, TypeSourceInfo *TInfo, StorageClass SC, StorageClass SCAsWritten, bool isInlineSpecified, - bool hasWrittenPrototype) { + bool hasWrittenPrototype, + bool isConstexprSpecified) { FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, T, TInfo, SC, SCAsWritten, - isInlineSpecified); + isInlineSpecified, + isConstexprSpecified); New->HasWrittenPrototype = hasWrittenPrototype; return New; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index b2806f0..321e40b 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -43,7 +43,7 @@ static bool StatSwitch = false; const char *Decl::getDeclKindName() const { switch (DeclKind) { - default: assert(0 && "Declaration not in DeclNodes.inc!"); + default: llvm_unreachable("Declaration not in DeclNodes.inc!"); #define DECL(DERIVED, BASE) case DERIVED: return #DERIVED; #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" @@ -62,7 +62,7 @@ void Decl::setInvalidDecl(bool Invalid) { const char *DeclContext::getDeclKindName() const { switch (DeclKind) { - default: assert(0 && "Declaration context not in DeclNodes.inc!"); + default: llvm_unreachable("Declaration context not in DeclNodes.inc!"); #define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED; #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" @@ -100,7 +100,7 @@ void Decl::PrintStats() { void Decl::add(Kind k) { switch (k) { - default: assert(0 && "Declaration not in DeclNodes.inc!"); + default: llvm_unreachable("Declaration not in DeclNodes.inc!"); #define DECL(DERIVED, BASE) case DERIVED: ++n##DERIVED##s; break; #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" @@ -133,14 +133,18 @@ bool Decl::isFunctionOrFunctionTemplate() const { return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this); } -bool Decl::isDefinedOutsideFunctionOrMethod() const { - for (const DeclContext *DC = getDeclContext(); - DC && !DC->isTranslationUnit(); +bool Decl::isTemplateDecl() const { + return isa<TemplateDecl>(this); +} + +const DeclContext *Decl::getParentFunctionOrMethod() const { + for (const DeclContext *DC = getDeclContext(); + DC && !DC->isTranslationUnit() && !DC->isNamespace(); DC = DC->getParent()) if (DC->isFunctionOrMethod()) - return false; + return DC; - return true; + return 0; } @@ -148,7 +152,7 @@ bool Decl::isDefinedOutsideFunctionOrMethod() const { // PrettyStackTraceDecl Implementation //===----------------------------------------------------------------------===// -void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const { +void PrettyStackTraceDecl::print(raw_ostream &OS) const { SourceLocation TheLoc = Loc; if (TheLoc.isInvalid() && TheDecl) TheLoc = TheDecl->getLocation(); @@ -265,13 +269,13 @@ bool Decl::isReferenced() const { static AvailabilityResult CheckAvailability(ASTContext &Context, const AvailabilityAttr *A, std::string *Message) { - llvm::StringRef TargetPlatform = Context.Target.getPlatformName(); - llvm::StringRef PrettyPlatformName + StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); + StringRef PrettyPlatformName = AvailabilityAttr::getPrettyPlatformName(TargetPlatform); if (PrettyPlatformName.empty()) PrettyPlatformName = TargetPlatform; - VersionTuple TargetMinVersion = Context.Target.getPlatformMinVersion(); + VersionTuple TargetMinVersion = Context.getTargetInfo().getPlatformMinVersion(); if (TargetMinVersion.empty()) return AR_Available; @@ -493,6 +497,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case UsingDirective: case ClassTemplateSpecialization: case ClassTemplatePartialSpecialization: + case ClassScopeFunctionSpecialization: case ObjCImplementation: case ObjCCategory: case ObjCCategoryImpl: @@ -566,8 +571,7 @@ Decl *Decl::castFromDeclContext (const DeclContext *D) { 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; + llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -586,8 +590,7 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { 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; + llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -627,7 +630,8 @@ void Decl::CheckAccessDeclContext() const { isa<ParmVarDecl>(this) || // FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have // AS_none as access specifier. - isa<CXXRecordDecl>(this)) + isa<CXXRecordDecl>(this) || + isa<ClassScopeFunctionSpecializationDecl>(this)) return; assert(Access != AS_none && @@ -812,11 +816,15 @@ DeclContext *DeclContext::getNextContext() { } std::pair<Decl *, Decl *> -DeclContext::BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls) { +DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls, + bool FieldsAlreadyLoaded) { // Build up a chain of declarations via the Decl::NextDeclInContext field. Decl *FirstNewDecl = 0; Decl *PrevDecl = 0; for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + if (FieldsAlreadyLoaded && isa<FieldDecl>(Decls[I])) + continue; + Decl *D = Decls[I]; if (PrevDecl) PrevDecl->NextDeclInContext = D; @@ -838,9 +846,9 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { // Notify that we have a DeclContext that is initializing. ExternalASTSource::Deserializing ADeclContext(Source); - + // Load the external declarations, if any. - llvm::SmallVector<Decl*, 64> Decls; + SmallVector<Decl*, 64> Decls; ExternalLexicalStorage = false; switch (Source->FindExternalLexicalDecls(this, Decls)) { case ELR_Success: @@ -855,17 +863,16 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { return; // We may have already loaded just the fields of this record, in which case - // don't add the decls, just replace the FirstDecl/LastDecl chain. + // we need to ignore them. + bool FieldsAlreadyLoaded = false; if (const RecordDecl *RD = dyn_cast<RecordDecl>(this)) - if (RD->LoadedFieldsFromExternalStorage) { - llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls); - return; - } - + FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage; + // Splice the newly-read declarations into the beginning of the list // of declarations. Decl *ExternalFirst, *ExternalLast; - llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls); + llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls, + FieldsAlreadyLoaded); ExternalLast->NextDeclInContext = FirstDecl; FirstDecl = ExternalFirst; if (!LastDecl) @@ -890,7 +897,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclContext::lookup_result ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, - llvm::SmallVectorImpl<NamedDecl*> &Decls) { + ArrayRef<NamedDecl*> Decls) { ASTContext &Context = DC->getParentASTContext();; StoredDeclsMap *Map; @@ -898,35 +905,17 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, Map = DC->CreateStoredDeclsMap(Context); StoredDeclsList &List = (*Map)[Name]; - for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + for (ArrayRef<NamedDecl*>::iterator + I = Decls.begin(), E = Decls.end(); I != E; ++I) { if (List.isNull()) - List.setOnlyValue(Decls[I]); + List.setOnlyValue(*I); else - List.AddSubsequentDecl(Decls[I]); + List.AddSubsequentDecl(*I); } return List.getLookupResult(); } -void ExternalASTSource::MaterializeVisibleDeclsForName(const DeclContext *DC, - DeclarationName Name, - llvm::SmallVectorImpl<NamedDecl*> &Decls) { - assert(DC->LookupPtr); - StoredDeclsMap &Map = *DC->LookupPtr; - - // If there's an entry in the table the visible decls for this name have - // already been deserialized. - if (Map.find(Name) == Map.end()) { - 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]); - } - } -} - DeclContext::decl_iterator DeclContext::noload_decls_begin() const { return decl_iterator(FirstDecl); } @@ -939,8 +928,6 @@ DeclContext::decl_iterator DeclContext::decls_begin() const { if (hasExternalLexicalStorage()) LoadLexicalDeclsFromExternalStorage(); - // FIXME: Check whether we need to load some declarations from - // external storage. return decl_iterator(FirstDecl); } @@ -988,6 +975,9 @@ void DeclContext::removeDecl(Decl *D) { if (isa<NamedDecl>(D)) { NamedDecl *ND = cast<NamedDecl>(D); + // Remove only decls that have a name + if (!ND->getDeclName()) return; + StoredDeclsMap *Map = getPrimaryContext()->LookupPtr; if (!Map) return; @@ -1038,12 +1028,10 @@ void DeclContext::buildLookup(DeclContext *DCtx) { if (D->getDeclContext() == DCtx) makeDeclVisibleInContextImpl(ND); - // Insert any forward-declared Objective-C interfaces into the lookup + // Insert any forward-declared Objective-C interface into the lookup // data structure. if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) - for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end(); - I != IEnd; ++I) - makeDeclVisibleInContextImpl(I->getInterface()); + makeDeclVisibleInContextImpl(Class->getForwardInterfaceDecl()); // If this declaration is itself a transparent declaration context or // inline namespace, add its members (recursively). @@ -1093,6 +1081,38 @@ DeclContext::lookup(DeclarationName Name) const { return const_cast<DeclContext*>(this)->lookup(Name); } +void DeclContext::localUncachedLookup(DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl *> &Results) { + Results.clear(); + + // If there's no external storage, just perform a normal lookup and copy + // the results. + if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage()) { + lookup_result LookupResults = lookup(Name); + Results.insert(Results.end(), LookupResults.first, LookupResults.second); + return; + } + + // If we have a lookup table, check there first. Maybe we'll get lucky. + if (LookupPtr) { + StoredDeclsMap::iterator Pos = LookupPtr->find(Name); + if (Pos != LookupPtr->end()) { + Results.insert(Results.end(), + Pos->second.getLookupResult().first, + Pos->second.getLookupResult().second); + return; + } + } + + // Slow case: grovel through the declarations in our chain looking for + // matches. + for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) + if (ND->getDeclName() == Name) + Results.push_back(ND); + } +} + DeclContext *DeclContext::getRedeclContext() { DeclContext *Ctx = this; // Skip through transparent contexts. @@ -1205,15 +1225,6 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) { DeclNameEntries.AddSubsequentDecl(D); } -void DeclContext::MaterializeVisibleDeclsFromExternalStorage() { - ExternalASTSource *Source = getParentASTContext().getExternalSource(); - assert(hasExternalVisibleStorage() && Source && "No external storage?"); - - if (!LookupPtr) - CreateStoredDeclsMap(getParentASTContext()); - Source->MaterializeVisibleDecls(this); -} - /// Returns iterator range [First, Last) of UsingDirectiveDecls stored within /// this context. DeclContext::udir_iterator_range diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index 4b59bf3..f3da67c 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -35,15 +35,16 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), HasMutableFields(false), HasTrivialDefaultConstructor(true), - HasConstExprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true), + HasConstexprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true), HasTrivialDestructor(true), HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), DeclaredMoveConstructor(false), DeclaredCopyAssignment(false), DeclaredMoveAssignment(false), - DeclaredDestructor(false), NumBases(0), NumVBases(0), Bases(), VBases(), - Definition(D), FirstFriend(0) { + DeclaredDestructor(false), FailedImplicitMoveConstructor(false), + FailedImplicitMoveAssignment(false), NumBases(0), NumVBases(0), Bases(), + VBases(), Definition(D), FirstFriend(0) { } CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, @@ -89,7 +90,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes; // The virtual bases of this class. - llvm::SmallVector<const CXXBaseSpecifier *, 8> VBases; + SmallVector<const CXXBaseSpecifier *, 8> VBases; data().Bases = new(C) CXXBaseSpecifier [NumBases]; data().NumBases = NumBases; @@ -287,7 +288,7 @@ bool CXXRecordDecl::isTriviallyCopyable() const { /// (if there is one). static CXXMethodDecl * GetBestOverloadCandidateSimple( - const llvm::SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) { + const SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) { if (Cands.empty()) return 0; if (Cands.size() == 1) @@ -313,7 +314,7 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(unsigned TypeQuals) const{ = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); unsigned FoundTQs; - llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; + SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; DeclContext::lookup_const_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); Con != ConEnd; ++Con) { @@ -349,7 +350,7 @@ CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this)); DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); - llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; + SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; DeclContext::lookup_const_iterator Op, OpEnd; for (llvm::tie(Op, OpEnd) = this->lookup(Name); Op != OpEnd; ++Op) { // C++ [class.copy]p9: @@ -502,18 +503,18 @@ NotASpecialMember:; // Note that we have a user-declared constructor. data().UserDeclaredConstructor = true; - // FIXME: Under C++0x, /only/ special member functions may be user-provided. - // This is probably a defect. - bool UserProvided = false; + // Technically, "user-provided" is only defined for special member + // functions, but the intent of the standard is clearly that it should apply + // to all functions. + bool UserProvided = Constructor->isUserProvided(); // C++0x [class.ctor]p5: // A default constructor is trivial if it is not user-provided [...] if (Constructor->isDefaultConstructor()) { data().DeclaredDefaultConstructor = true; - if (Constructor->isUserProvided()) { + if (UserProvided) { data().HasTrivialDefaultConstructor = false; data().UserProvidedDefaultConstructor = true; - UserProvided = true; } } @@ -527,10 +528,8 @@ NotASpecialMember:; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if it is not // user-provided [...] - if (Constructor->isUserProvided()) { + if (UserProvided) data().HasTrivialCopyConstructor = false; - UserProvided = true; - } } else if (Constructor->isMoveConstructor()) { data().UserDeclaredMoveConstructor = true; data().DeclaredMoveConstructor = true; @@ -538,17 +537,14 @@ NotASpecialMember:; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if it is not // user-provided [...] - if (Constructor->isUserProvided()) { + if (UserProvided) data().HasTrivialMoveConstructor = false; - UserProvided = true; - } } } - if (Constructor->isConstExpr() && - !Constructor->isCopyOrMoveConstructor()) { - // Record if we see any constexpr constructors which are niether copy + if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) { + // Record if we see any constexpr constructors which are neither copy // nor move constructors. - data().HasConstExprNonCopyMoveConstructor = true; + data().HasConstexprNonCopyMoveConstructor = true; } // C++ [dcl.init.aggr]p1: @@ -657,6 +653,13 @@ NotASpecialMember:; // Handle non-static data members. if (FieldDecl *Field = dyn_cast<FieldDecl>(D)) { + // C++ [class.bit]p2: + // A declaration for a bit-field that omits the identifier declares an + // unnamed bit-field. Unnamed bit-fields are not members and cannot be + // initialized. + if (Field->isUnnamedBitfield()) + return; + // C++ [dcl.init.aggr]p1: // An aggregate is an array or a class (clause 9) with [...] no // private or protected non-static data members (clause 11). @@ -675,7 +678,7 @@ NotASpecialMember:; case AS_private: data().HasPrivateFields = true; break; case AS_protected: data().HasProtectedFields = true; break; case AS_public: data().HasPublicFields = true; break; - case AS_none: assert(0 && "Invalid access specifier"); + case AS_none: llvm_unreachable("Invalid access specifier"); }; if ((data().HasPrivateFields + data().HasProtectedFields + data().HasPublicFields) > 1) @@ -716,7 +719,11 @@ NotASpecialMember:; } // Record if this field is the first non-literal field or base. - if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) + // As a slight variation on the standard, we regard mutable members as being + // non-literal, since mutating a constexpr variable would break C++11 + // constant expression semantics. + if ((!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) || + Field->isMutable()) data().HasNonLiteralTypeFieldsOrBases = true; if (Field->hasInClassInitializer()) { @@ -827,15 +834,11 @@ NotASpecialMember:; // If this is not a zero-length bit-field, then the class is not empty. if (data().Empty) { - if (!Field->getBitWidth()) + if (!Field->isBitField() || + (!Field->getBitWidth()->isTypeDependent() && + !Field->getBitWidth()->isValueDependent() && + Field->getBitWidthValue(Context) != 0)) data().Empty = false; - else if (!Field->getBitWidth()->isTypeDependent() && - !Field->getBitWidth()->isValueDependent()) { - llvm::APSInt Bits; - if (Field->getBitWidth()->isIntegerConstantExpr(Bits, Context)) - if (!!Bits) - data().Empty = false; - } } } @@ -1057,7 +1060,7 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { return; } - assert(false && "Not a class template or member class specialization"); + llvm_unreachable("Not a class template or member class specialization"); } CXXDestructorDecl *CXXRecordDecl::getDestructor() const { @@ -1160,9 +1163,10 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isStatic, StorageClass SCAsWritten, bool isInline, - SourceLocation EndLocation) { + bool isConstexpr, SourceLocation EndLocation) { return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo, - isStatic, SCAsWritten, isInline, EndLocation); + isStatic, SCAsWritten, isInline, isConstexpr, + EndLocation); } bool CXXMethodDecl::isUsualDeallocationFunction() const { @@ -1402,7 +1406,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const { CXXConstructorDecl * CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) { return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationNameInfo(), - QualType(), 0, false, false, false); + QualType(), 0, false, false, false, false); } CXXConstructorDecl * @@ -1410,14 +1414,14 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isExplicit, - bool isInline, - bool isImplicitlyDeclared) { + bool isExplicit, bool isInline, + bool isImplicitlyDeclared, bool isConstexpr) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); return new (C) CXXConstructorDecl(RD, StartLoc, NameInfo, T, TInfo, - isExplicit, isInline, isImplicitlyDeclared); + isExplicit, isInline, isImplicitlyDeclared, + isConstexpr); } bool CXXConstructorDecl::isDefaultConstructor() const { @@ -1545,8 +1549,7 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, - bool isImplicitlyDeclared) { + bool isInline, bool isImplicitlyDeclared) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXDestructorName && "Name must refer to a destructor"); @@ -1557,7 +1560,7 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, CXXConversionDecl * CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) { return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(), - QualType(), 0, false, false, + QualType(), 0, false, false, false, SourceLocation()); } @@ -1567,12 +1570,13 @@ CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicit, - SourceLocation EndLocation) { + bool isConstexpr, SourceLocation EndLocation) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConversionFunctionName && "Name must refer to a conversion function"); return new (C) CXXConversionDecl(RD, StartLoc, NameInfo, T, TInfo, - isInline, isExplicit, EndLocation); + isInline, isExplicit, isConstexpr, + EndLocation); } LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, @@ -1696,8 +1700,7 @@ static const char *getAccessName(AccessSpecifier AS) { switch (AS) { default: case AS_none: - assert("Invalid access specifier!"); - return 0; + llvm_unreachable("Invalid access specifier!"); case AS_public: return "public"; case AS_private: diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index 557b681..a589b7f 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Stmt.h" +#include "clang/AST/ASTMutationListener.h" #include "llvm/ADT/STLExtras.h" using namespace clang; @@ -185,7 +186,7 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( // Check for duplicate protocol in class's protocol list. // This is O(n*m). But it is extremely rare and number of protocols in // class or its extension are very few. - llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs; + SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs; for (unsigned i = 0; i < ExtNum; i++) { bool protocolExists = false; ObjCProtocolDecl *ProtoInExtension = ExtList[i]; @@ -337,17 +338,60 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C, bool isInstance, bool isVariadic, bool isSynthesized, + bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl, - bool HasRelatedResultType, - unsigned numSelectorArgs) { + bool HasRelatedResultType) { return new (C) ObjCMethodDecl(beginLoc, endLoc, SelInfo, T, ResultTInfo, contextDecl, isInstance, - isVariadic, isSynthesized, isDefined, + isVariadic, isSynthesized, isImplicitlyDeclared, + isDefined, impControl, - HasRelatedResultType, - numSelectorArgs); + HasRelatedResultType); +} + +void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) { + assert(PrevMethod); + getASTContext().setObjCMethodRedeclaration(PrevMethod, this); + IsRedeclaration = true; + PrevMethod->HasRedeclaration = true; +} + +void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, + ArrayRef<ParmVarDecl*> Params, + ArrayRef<SourceLocation> SelLocs) { + ParamsAndSelLocs = 0; + NumParams = Params.size(); + if (Params.empty() && SelLocs.empty()) + return; + + unsigned Size = sizeof(ParmVarDecl *) * NumParams + + sizeof(SourceLocation) * SelLocs.size(); + ParamsAndSelLocs = C.Allocate(Size); + std::copy(Params.begin(), Params.end(), getParams()); + std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); +} + +void ObjCMethodDecl::getSelectorLocs( + SmallVectorImpl<SourceLocation> &SelLocs) const { + for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) + SelLocs.push_back(getSelectorLoc(i)); +} + +void ObjCMethodDecl::setMethodParams(ASTContext &C, + ArrayRef<ParmVarDecl*> Params, + ArrayRef<SourceLocation> SelLocs) { + assert((!SelLocs.empty() || isImplicit()) && + "No selector locs for non-implicit method"); + if (isImplicit()) + return setParamsAndSelLocs(C, Params, ArrayRef<SourceLocation>()); + + SelLocsKind = hasStandardSelectorLocs(getSelector(), SelLocs, Params, EndLoc); + if (SelLocsKind != SelLoc_NonStandard) + return setParamsAndSelLocs(C, Params, ArrayRef<SourceLocation>()); + + setParamsAndSelLocs(C, Params, SelLocs); } /// \brief A definition will return its interface declaration. @@ -356,6 +400,11 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C, ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() { ASTContext &Ctx = getASTContext(); ObjCMethodDecl *Redecl = 0; + if (HasRedeclaration) + Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this)); + if (Redecl) + return Redecl; + Decl *CtxD = cast<Decl>(getDeclContext()); if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) { @@ -377,6 +426,12 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() { Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); } + if (!Redecl && isRedeclaration()) { + // This is the last redeclaration, go back to the first method. + return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), + isInstanceMethod()); + } + return Redecl ? Redecl : this; } @@ -444,6 +499,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { // These selectors have a conventional meaning only for instance methods. case OMF_dealloc: + case OMF_finalize: case OMF_retain: case OMF_release: case OMF_autorelease: @@ -545,8 +601,7 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { return IMD->getClassInterface(); assert(!isa<ObjCProtocolDecl>(getDeclContext()) && "It's a protocol method"); - assert(false && "unknown method context"); - return 0; + llvm_unreachable("unknown method context"); } //===----------------------------------------------------------------------===// @@ -566,11 +621,10 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C, ObjCInterfaceDecl:: ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, SourceLocation CLoc, bool FD, bool isInternal) - : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id), + : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc), TypeForDecl(0), SuperClass(0), CategoryList(0), IvarList(0), - ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false), - ClassLoc(CLoc) { + ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false) { } void ObjCInterfaceDecl::LoadExternalDefinition() const { @@ -756,8 +810,7 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, ID = IM->getClassInterface(); if (BW) IM->setHasSynthBitfield(true); - } - else { + } else { ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC); ID = CD->getClassInterface(); if (BW) @@ -778,8 +831,7 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { default: case ObjCCategoryImpl: case ObjCProtocol: - assert(0 && "invalid ivar container!"); - return 0; + llvm_unreachable("invalid ivar container!"); // Ivars can only appear in class extension categories. case ObjCCategory: { @@ -812,9 +864,10 @@ ObjCAtDefsFieldDecl //===----------------------------------------------------------------------===// ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - IdentifierInfo *Id) { - return new (C) ObjCProtocolDecl(DC, L, Id); + IdentifierInfo *Id, + SourceLocation nameLoc, + SourceLocation atStartLoc) { + return new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc); } ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { @@ -850,36 +903,31 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, //===----------------------------------------------------------------------===// ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const *Elts, - const SourceLocation *Locs, - unsigned nElts, + ObjCInterfaceDecl *const Elt, + const SourceLocation Loc, ASTContext &C) : Decl(ObjCClass, DC, L) { - setClassList(C, Elts, Locs, nElts); -} - -void ObjCClassDecl::setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, - const SourceLocation *Locs, unsigned Num) { - ForwardDecls = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef)*Num, - llvm::alignOf<ObjCClassRef>()); - for (unsigned i = 0; i < Num; ++i) - new (&ForwardDecls[i]) ObjCClassRef(List[i], Locs[i]); - - NumDecls = Num; + setClass(C, Elt, Loc); } ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const *Elts, - const SourceLocation *Locs, - unsigned nElts) { - return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C); + ObjCInterfaceDecl *const Elt, + const SourceLocation Loc) { + return new (C) ObjCClassDecl(DC, L, Elt, Loc, C); } +void ObjCClassDecl::setClass(ASTContext &C, ObjCInterfaceDecl*const Cls, + const SourceLocation Loc) { + + ForwardDecl = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef), + llvm::alignOf<ObjCClassRef>()); + new (ForwardDecl) ObjCClassRef(Cls, Loc); +} + SourceRange ObjCClassDecl::getSourceRange() const { // FIXME: We should include the semicolon - assert(NumDecls); - return SourceRange(getLocation(), ForwardDecls[NumDecls-1].getLocation()); + return SourceRange(getLocation(), ForwardDecl->getLocation()); } //===----------------------------------------------------------------------===// @@ -912,8 +960,25 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation AtLoc, SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, - IdentifierInfo *Id) { - return new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id); + IdentifierInfo *Id, + ObjCInterfaceDecl *IDecl) { + ObjCCategoryDecl *CatDecl = new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, + CategoryNameLoc, Id, + IDecl); + if (IDecl) { + // Link this category into its class's category list. + CatDecl->NextClassCategory = IDecl->getCategoryList(); + IDecl->setCategoryList(CatDecl); + if (ASTMutationListener *L = C.getASTMutationListener()) + L->AddedObjCCategoryToInterface(CatDecl, IDecl); + } + + return CatDecl; +} + +ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(), + SourceLocation(), 0, 0); } ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const { @@ -932,9 +997,12 @@ void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) { ObjCCategoryImplDecl * ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L,IdentifierInfo *Id, - ObjCInterfaceDecl *ClassInterface) { - return new (C) ObjCCategoryImplDecl(DC, L, Id, ClassInterface); + IdentifierInfo *Id, + ObjCInterfaceDecl *ClassInterface, + SourceLocation nameLoc, + SourceLocation atStartLoc) { + return new (C) ObjCCategoryImplDecl(DC, Id, ClassInterface, + nameLoc, atStartLoc); } ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { @@ -997,7 +1065,7 @@ FindPropertyImplDecl(IdentifierInfo *Id) const { return 0; } -llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS, +raw_ostream &clang::operator<<(raw_ostream &OS, const ObjCCategoryImplDecl *CID) { OS << CID->getName(); return OS; @@ -1009,13 +1077,28 @@ llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS, ObjCImplementationDecl * ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, ObjCInterfaceDecl *ClassInterface, - ObjCInterfaceDecl *SuperDecl) { - return new (C) ObjCImplementationDecl(DC, L, ClassInterface, SuperDecl); + ObjCInterfaceDecl *SuperDecl, + SourceLocation nameLoc, + SourceLocation atStartLoc) { + return new (C) ObjCImplementationDecl(DC, ClassInterface, SuperDecl, + nameLoc, atStartLoc); +} + +void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, + CXXCtorInitializer ** initializers, + unsigned numInitializers) { + if (numInitializers > 0) { + NumIvarInitializers = numInitializers; + CXXCtorInitializer **ivarInitializers = + new (C) CXXCtorInitializer*[NumIvarInitializers]; + memcpy(ivarInitializers, initializers, + numInitializers * sizeof(CXXCtorInitializer*)); + IvarInitializers = ivarInitializers; + } } -llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS, +raw_ostream &clang::operator<<(raw_ostream &OS, const ObjCImplementationDecl *ID) { OS << ID->getName(); return OS; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 19554a3..08a1ab5 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -24,22 +24,25 @@ using namespace clang; namespace { class DeclPrinter : public DeclVisitor<DeclPrinter> { - llvm::raw_ostream &Out; + raw_ostream &Out; ASTContext &Context; PrintingPolicy Policy; unsigned Indentation; + bool PrintInstantiation; - llvm::raw_ostream& Indent() { return Indent(Indentation); } - llvm::raw_ostream& Indent(unsigned Indentation); - void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls); + raw_ostream& Indent() { return Indent(Indentation); } + raw_ostream& Indent(unsigned Indentation); + void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls); void Print(AccessSpecifier AS); public: - DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context, + DeclPrinter(raw_ostream &Out, ASTContext &Context, const PrintingPolicy &Policy, - unsigned Indentation = 0) - : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { } + unsigned Indentation = 0, + bool PrintInstantiation = false) + : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation), + PrintInstantiation(PrintInstantiation) { } void VisitDeclContext(DeclContext *DC, bool Indent = true); @@ -62,6 +65,8 @@ namespace { void VisitCXXRecordDecl(CXXRecordDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitTemplateDecl(const TemplateDecl *D); + void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); + void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCClassDecl(ObjCClassDecl *D); void VisitObjCImplementationDecl(ObjCImplementationDecl *D); @@ -77,16 +82,20 @@ namespace { void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); void VisitUsingDecl(UsingDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); + + void PrintTemplateParameters(const TemplateParameterList *Params, + const TemplateArgumentList *Args); }; } -void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const { - print(Out, getASTContext().PrintingPolicy, Indentation); +void Decl::print(raw_ostream &Out, unsigned Indentation, + bool PrintInstantiation) const { + print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation); } -void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation) const { - DeclPrinter Printer(Out, getASTContext(), Policy, Indentation); +void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, + unsigned Indentation, bool PrintInstantiation) const { + DeclPrinter Printer(Out, getASTContext(), Policy, Indentation, PrintInstantiation); Printer.Visit(const_cast<Decl*>(this)); } @@ -105,7 +114,7 @@ static QualType GetBaseType(QualType T) { else if (const VectorType *VTy = BaseType->getAs<VectorType>()) BaseType = VTy->getElementType(); else - assert(0 && "Unknown declarator!"); + llvm_unreachable("Unknown declarator!"); } return BaseType; } @@ -119,7 +128,7 @@ static QualType getDeclType(Decl* D) { } void Decl::printGroup(Decl** Begin, unsigned NumDecls, - llvm::raw_ostream &Out, const PrintingPolicy &Policy, + raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation) { if (NumDecls == 1) { (*Begin)->print(Out, Policy, Indentation); @@ -132,7 +141,7 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls, ++Begin; PrintingPolicy SubPolicy(Policy); - if (TD && TD->isDefinition()) { + if (TD && TD->isCompleteDefinition()) { TD->print(Out, Policy, Indentation); Out << " "; SubPolicy.SuppressTag = true; @@ -159,7 +168,7 @@ void DeclContext::dumpDeclContext() const { DC = DC->getParent(); ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); - DeclPrinter Printer(llvm::errs(), Ctx, Ctx.PrintingPolicy, 0); + DeclPrinter Printer(llvm::errs(), Ctx, Ctx.getPrintingPolicy(), 0); Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); } @@ -167,13 +176,13 @@ void Decl::dump() const { print(llvm::errs()); } -llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) { +raw_ostream& DeclPrinter::Indent(unsigned Indentation) { for (unsigned i = 0; i != Indentation; ++i) Out << " "; return Out; } -void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) { +void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) { this->Indent(); Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); Out << ";\n"; @@ -183,7 +192,7 @@ void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) { void DeclPrinter::Print(AccessSpecifier AS) { switch(AS) { - case AS_none: assert(0 && "No access specifier!"); break; + case AS_none: llvm_unreachable("No access specifier!"); case AS_public: Out << "public"; break; case AS_protected: Out << "protected"; break; case AS_private: Out << "private"; break; @@ -198,7 +207,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (Indent) Indentation += Policy.Indentation; - llvm::SmallVector<Decl*, 2> Decls; + SmallVector<Decl*, 2> Decls; for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); D != DEnd; ++D) { @@ -304,8 +313,12 @@ void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { std::string S = D->getNameAsString(); D->getUnderlyingType().getAsStringInternal(S, Policy); - if (!Policy.SuppressSpecifiers) + if (!Policy.SuppressSpecifiers) { Out << "typedef "; + + if (D->isModulePrivate()) + Out << "__module_private__ "; + } Out << S; } @@ -315,6 +328,8 @@ void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { } void DeclPrinter::VisitEnumDecl(EnumDecl *D) { + if (!Policy.SuppressSpecifiers && D->isModulePrivate()) + Out << "__module_private__ "; Out << "enum "; if (D->isScoped()) { if (D->isScopedUsingClassTag()) @@ -322,7 +337,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) { else Out << "struct "; } - Out << D; + Out << *D; if (D->isFixed()) { std::string Underlying; @@ -330,7 +345,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) { Out << " : " << Underlying; } - if (D->isDefinition()) { + if (D->isCompleteDefinition()) { Out << " {\n"; VisitDeclContext(D); Indent() << "}"; @@ -338,11 +353,13 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) { } void DeclPrinter::VisitRecordDecl(RecordDecl *D) { + if (!Policy.SuppressSpecifiers && D->isModulePrivate()) + Out << "__module_private__ "; Out << D->getKindName(); if (D->getIdentifier()) - Out << ' ' << D; + Out << ' ' << *D; - if (D->isDefinition()) { + if (D->isCompleteDefinition()) { Out << " {\n"; VisitDeclContext(D); Indent() << "}"; @@ -350,7 +367,7 @@ void DeclPrinter::VisitRecordDecl(RecordDecl *D) { } void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { - Out << D; + Out << *D; if (Expr *Init = D->getInitExpr()) { Out << " = "; Init->printPretty(Out, Context, 0, Policy, Indentation); @@ -364,11 +381,13 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { case SC_Extern: Out << "extern "; break; case SC_Static: Out << "static "; break; case SC_PrivateExtern: Out << "__private_extern__ "; break; - case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions"); + case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal: + llvm_unreachable("invalid for functions"); } - if (D->isInlineSpecified()) Out << "inline "; + if (D->isInlineSpecified()) Out << "inline "; if (D->isVirtualAsWritten()) Out << "virtual "; + if (D->isModulePrivate()) Out << "__module_private__ "; } PrintingPolicy SubPolicy(Policy); @@ -449,6 +468,10 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->hasAttr<NoReturnAttr>()) Proto += " __attribute((noreturn))"; + + if (D->hasAttr<ReturnsTwiceAttr>()) + Proto += " __attribute((returns_twice))"; + if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { bool HasInitializerList = false; for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), @@ -468,10 +491,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (BMInitializer->isAnyMemberInitializer()) { FieldDecl *FD = BMInitializer->getAnyMember(); - Out << FD; + Out << *FD; } else { - Out << QualType(BMInitializer->getBaseClass(), - 0).getAsString(Policy); + Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); } Out << "("; @@ -549,6 +571,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { void DeclPrinter::VisitFieldDecl(FieldDecl *D) { if (!Policy.SuppressSpecifiers && D->isMutable()) Out << "mutable "; + if (!Policy.SuppressSpecifiers && D->isModulePrivate()) + Out << "__module_private__ "; std::string Name = D->getNameAsString(); D->getType().getAsStringInternal(Name, Policy); @@ -577,6 +601,8 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { if (!Policy.SuppressSpecifiers && D->isThreadSpecified()) Out << "__thread "; + if (!Policy.SuppressSpecifiers && D->isModulePrivate()) + Out << "__module_private__ "; std::string Name = D->getNameAsString(); QualType T = D->getType(); @@ -621,7 +647,7 @@ void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { // C++ declarations //---------------------------------------------------------------------------- void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { - Out << "namespace " << D << " {\n"; + Out << "namespace " << *D << " {\n"; VisitDeclContext(D); Indent() << "}"; } @@ -630,22 +656,24 @@ void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { Out << "using namespace "; if (D->getQualifier()) D->getQualifier()->print(Out, Policy); - Out << D->getNominatedNamespaceAsWritten(); + Out << *D->getNominatedNamespaceAsWritten(); } void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { - Out << "namespace " << D << " = "; + Out << "namespace " << *D << " = "; if (D->getQualifier()) D->getQualifier()->print(Out, Policy); - Out << D->getAliasedNamespace(); + Out << *D->getAliasedNamespace(); } void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { + if (!Policy.SuppressSpecifiers && D->isModulePrivate()) + Out << "__module_private__ "; Out << D->getKindName(); if (D->getIdentifier()) - Out << ' ' << D; + Out << ' ' << *D; - if (D->isDefinition()) { + if (D->isCompleteDefinition()) { // Print the base classes if (D->getNumBases()) { Out << " : "; @@ -694,10 +722,13 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { Visit(*D->decls_begin()); } -void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { +void DeclPrinter::PrintTemplateParameters( + const TemplateParameterList *Params, const TemplateArgumentList *Args = 0) { + assert(Params); + assert(!Args || Params->size() == Args->size()); + Out << "template <"; - TemplateParameterList *Params = D->getTemplateParameters(); for (unsigned i = 0, e = Params->size(); i != e; ++i) { if (i != 0) Out << ", "; @@ -716,7 +747,10 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { Out << TTP->getNameAsString(); - if (TTP->hasDefaultArgument()) { + if (Args) { + Out << " = "; + Args->get(i).print(Policy, Out); + } else if (TTP->hasDefaultArgument()) { Out << " = "; Out << TTP->getDefaultArgument().getAsString(Policy); }; @@ -732,7 +766,10 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { Out << Name->getName(); } - if (NTTP->hasDefaultArgument()) { + if (Args) { + Out << " = "; + Args->get(i).print(Policy, Out); + } else if (NTTP->hasDefaultArgument()) { Out << " = "; NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy, Indentation); @@ -745,6 +782,10 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { } Out << "> "; +} + +void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { + PrintTemplateParameters(D->getTemplateParameters()); if (const TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { @@ -757,17 +798,39 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { } } +void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + if (PrintInstantiation) { + TemplateParameterList *Params = D->getTemplateParameters(); + for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end(); + I != E; ++I) { + PrintTemplateParameters(Params, (*I)->getTemplateSpecializationArgs()); + Visit(*I); + } + } + + return VisitRedeclarableTemplateDecl(D); +} + +void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { + if (PrintInstantiation) { + TemplateParameterList *Params = D->getTemplateParameters(); + for (ClassTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end(); + I != E; ++I) { + PrintTemplateParameters(Params, &(*I)->getTemplateArgs()); + Visit(*I); + Out << '\n'; + } + } + + return VisitRedeclarableTemplateDecl(D); +} + //---------------------------------------------------------------------------- // Objective-C declarations //---------------------------------------------------------------------------- void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { - Out << "@class "; - for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); - I != E; ++I) { - if (I != D->begin()) Out << ", "; - Out << I->getInterface(); - } + Out << "@class " << *D->getForwardInterfaceDecl(); } void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { @@ -783,9 +846,9 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), E = OMD->param_end(); PI != E; ++PI) { // FIXME: selector is missing here! - pos = name.find_first_of(":", lastPos); + pos = name.find_first_of(':', lastPos); Out << " " << name.substr(lastPos, pos - lastPos); - Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << *PI; + Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << **PI; lastPos = pos + 1; } @@ -807,7 +870,7 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { ObjCInterfaceDecl *SID = OID->getSuperClass(); if (SID) - Out << "@implementation " << I << " : " << SID; + Out << "@implementation " << I << " : " << *SID; else Out << "@implementation " << I; Out << "\n"; @@ -820,7 +883,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { ObjCInterfaceDecl *SID = OID->getSuperClass(); if (SID) - Out << "@interface " << I << " : " << SID; + Out << "@interface " << I << " : " << *SID; else Out << "@interface " << I; @@ -829,7 +892,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { if (!Protocols.empty()) { for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) - Out << (I == Protocols.begin() ? '<' : ',') << *I; + Out << (I == Protocols.begin() ? '<' : ',') << **I; } if (!Protocols.empty()) @@ -840,7 +903,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { Indentation += Policy.Indentation; for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), E = OID->ivar_end(); I != E; ++I) { - Indent() << (*I)->getType().getAsString(Policy) << ' ' << *I << ";\n"; + Indent() << (*I)->getType().getAsString(Policy) << ' ' << **I << ";\n"; } Indentation -= Policy.Indentation; Out << "}\n"; @@ -857,18 +920,18 @@ void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { E = D->protocol_end(); I != E; ++I) { if (I != D->protocol_begin()) Out << ", "; - Out << *I; + Out << **I; } } void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { - Out << "@protocol " << PID << '\n'; + Out << "@protocol " << *PID << '\n'; VisitDeclContext(PID, false); Out << "@end"; } void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { - Out << "@implementation " << PID->getClassInterface() << '(' << PID << ")\n"; + Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n"; VisitDeclContext(PID, false); Out << "@end"; @@ -876,7 +939,7 @@ void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { } void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { - Out << "@interface " << PID->getClassInterface() << '(' << PID << ")\n"; + Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n"; VisitDeclContext(PID, false); Out << "@end"; @@ -884,8 +947,8 @@ void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { } void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { - Out << "@compatibility_alias " << AID - << ' ' << AID->getClassInterface() << ";\n"; + Out << "@compatibility_alias " << *AID + << ' ' << *AID->getClassInterface() << ";\n"; } /// PrintObjCPropertyDecl - print a property declaration. @@ -904,58 +967,60 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { ObjCPropertyDecl::OBJC_PR_readonly) { Out << (first ? ' ' : ',') << "readonly"; first = false; - } + } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { - Out << (first ? ' ' : ',') << "getter = " - << PDecl->getGetterName().getAsString(); - first = false; - } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { - Out << (first ? ' ' : ',') << "setter = " - << PDecl->getSetterName().getAsString(); - first = false; - } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { + Out << (first ? ' ' : ',') << "getter = " + << PDecl->getGetterName().getAsString(); + first = false; + } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { + Out << (first ? ' ' : ',') << "setter = " + << PDecl->getSetterName().getAsString(); + first = false; + } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { - Out << (first ? ' ' : ',') << "assign"; - first = false; - } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { + Out << (first ? ' ' : ',') << "assign"; + first = false; + } - if (PDecl->getPropertyAttributes() & - ObjCPropertyDecl::OBJC_PR_readwrite) { - Out << (first ? ' ' : ',') << "readwrite"; - first = false; - } + if (PDecl->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_readwrite) { + Out << (first ? ' ' : ',') << "readwrite"; + first = false; + } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { - Out << (first ? ' ' : ',') << "retain"; - first = false; - } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { + Out << (first ? ' ' : ',') << "retain"; + first = false; + } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) { - Out << (first ? ' ' : ',') << "strong"; - first = false; - } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) { + Out << (first ? ' ' : ',') << "strong"; + first = false; + } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { - Out << (first ? ' ' : ',') << "copy"; - first = false; - } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { + Out << (first ? ' ' : ',') << "copy"; + first = false; + } - if (PDecl->getPropertyAttributes() & - ObjCPropertyDecl::OBJC_PR_nonatomic) { - Out << (first ? ' ' : ',') << "nonatomic"; - first = false; - } - if (PDecl->getPropertyAttributes() & - ObjCPropertyDecl::OBJC_PR_atomic) { - Out << (first ? ' ' : ',') << "atomic"; - first = false; - } - Out << " )"; + if (PDecl->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_nonatomic) { + Out << (first ? ' ' : ',') << "nonatomic"; + first = false; + } + if (PDecl->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_atomic) { + Out << (first ? ' ' : ',') << "atomic"; + first = false; + } + + (void) first; // Silence dead store warning due to idiomatic code. + Out << " )"; } - Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl; + Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << *PDecl; } void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { @@ -963,15 +1028,15 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { Out << "@synthesize "; else Out << "@dynamic "; - Out << PID->getPropertyDecl(); + Out << *PID->getPropertyDecl(); if (PID->getPropertyIvarDecl()) - Out << '=' << PID->getPropertyIvarDecl(); + Out << '=' << *PID->getPropertyIvarDecl(); } void DeclPrinter::VisitUsingDecl(UsingDecl *D) { Out << "using "; D->getQualifier()->print(Out, Policy); - Out << D; + Out << *D; } void diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index bc375d0a..558a4cc 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -348,7 +348,7 @@ void ClassTemplateDecl::AddPartialSpecialization( } void ClassTemplateDecl::getPartialSpecializations( - llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) { + SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) { llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &PartialSpecs = getPartialSpecializations(); PS.clear(); @@ -406,7 +406,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { // pack. ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); - llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + SmallVector<TemplateArgument, 16> TemplateArgs; TemplateArgs.resize(Params->size()); GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data()); CommonPtr->InjectedClassNameType @@ -563,6 +563,24 @@ TemplateArgumentList::CreateCopy(ASTContext &Context, return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true); } +FunctionTemplateSpecializationInfo * +FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD, + FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, + const TemplateArgumentList *TemplateArgs, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation POI) { + const ASTTemplateArgumentListInfo *ArgsAsWritten = 0; + if (TemplateArgsAsWritten) + ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C, + *TemplateArgsAsWritten); + + return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK, + TemplateArgs, + ArgsAsWritten, + POI); +} + //===----------------------------------------------------------------------===// // ClassTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// @@ -638,15 +656,27 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const { SourceRange ClassTemplateSpecializationDecl::getSourceRange() const { - if (!ExplicitInfo) - return SourceRange(); - SourceLocation Begin = getExternLoc(); - if (Begin.isInvalid()) - Begin = getTemplateKeywordLoc(); - SourceLocation End = getRBraceLoc(); - if (End.isInvalid()) - End = getTypeAsWritten()->getTypeLoc().getEndLoc(); - return SourceRange(Begin, End); + if (ExplicitInfo) { + SourceLocation Begin = getExternLoc(); + if (Begin.isInvalid()) + Begin = getTemplateKeywordLoc(); + SourceLocation End = getRBraceLoc(); + if (End.isInvalid()) + End = getTypeAsWritten()->getTypeLoc().getEndLoc(); + return SourceRange(Begin, End); + } + else { + // No explicit info available. + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + inst_from = getInstantiatedFrom(); + if (inst_from.isNull()) + return getSpecializedTemplate()->getSourceRange(); + if (ClassTemplateDecl *ctd = inst_from.dyn_cast<ClassTemplateDecl*>()) + return ctd->getSourceRange(); + return inst_from.get<ClassTemplatePartialSpecializationDecl*>() + ->getSourceRange(); + } } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp index 72c0e9d..bf647ed 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp @@ -193,8 +193,7 @@ DeclarationName::NameKind DeclarationName::getNameKind() const { } // Can't actually get here. - assert(0 && "This should be unreachable!"); - return Identifier; + llvm_unreachable("This should be unreachable!"); } bool DeclarationName::isDependentName() const { @@ -209,7 +208,7 @@ std::string DeclarationName::getAsString() const { return OS.str(); } -void DeclarationName::printName(llvm::raw_ostream &OS) const { +void DeclarationName::printName(raw_ostream &OS) const { switch (getNameKind()) { case Identifier: if (const IdentifierInfo *II = getAsIdentifierInfo()) @@ -225,7 +224,7 @@ void DeclarationName::printName(llvm::raw_ostream &OS) const { case CXXConstructorName: { QualType ClassType = getCXXNameType(); if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) - OS << ClassRec->getDecl(); + OS << *ClassRec->getDecl(); else OS << ClassType.getAsString(); return; @@ -235,7 +234,7 @@ void DeclarationName::printName(llvm::raw_ostream &OS) const { OS << '~'; QualType Type = getCXXNameType(); if (const RecordType *Rec = Type->getAs<RecordType>()) - OS << Rec->getDecl(); + OS << *Rec->getDecl(); else OS << Type.getAsString(); return; @@ -266,7 +265,7 @@ void DeclarationName::printName(llvm::raw_ostream &OS) const { OS << "operator "; QualType Type = getCXXNameType(); if (const RecordType *Rec = Type->getAs<RecordType>()) - OS << Rec->getDecl(); + OS << *Rec->getDecl(); else OS << Type.getAsString(); return; @@ -276,7 +275,7 @@ void DeclarationName::printName(llvm::raw_ostream &OS) const { return; } - assert(false && "Unexpected declaration name kind"); + llvm_unreachable("Unexpected declaration name kind"); } QualType DeclarationName::getCXXNameType() const { @@ -338,9 +337,8 @@ void *DeclarationName::getFETokenInfoAsVoid() const { return getCXXLiteralIdentifier()->getFETokenInfo<void>(); default: - assert(false && "Declaration name has no FETokenInfo"); + llvm_unreachable("Declaration name has no FETokenInfo"); } - return 0; } void DeclarationName::setFETokenInfo(void *T) { @@ -364,7 +362,7 @@ void DeclarationName::setFETokenInfo(void *T) { break; default: - assert(false && "Declaration name has no FETokenInfo"); + llvm_unreachable("Declaration name has no FETokenInfo"); } } @@ -562,7 +560,7 @@ std::string DeclarationNameInfo::getAsString() const { return OS.str(); } -void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const { +void DeclarationNameInfo::printName(raw_ostream &OS) const { switch (Name.getNameKind()) { case DeclarationName::Identifier: case DeclarationName::ObjCZeroArgSelector: @@ -588,7 +586,7 @@ void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const { Name.printName(OS); return; } - assert(false && "Unexpected declaration name kind"); + llvm_unreachable("Unexpected declaration name kind"); } SourceLocation DeclarationNameInfo::getEndLoc() const { @@ -621,6 +619,5 @@ SourceLocation DeclarationNameInfo::getEndLoc() const { case DeclarationName::CXXUsingDirective: return NameLoc; } - assert(false && "Unexpected declaration name kind"); - return SourceLocation(); + llvm_unreachable("Unexpected declaration name kind"); } diff --git a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp index dfe0119..2568ada 100644 --- a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp @@ -53,9 +53,9 @@ enum NodeState { }; struct Node { - llvm::StringRef Name; + StringRef Name; NodeState State; - Node(llvm::StringRef name) : Name(name), State(NS_Attrs) {} + Node(StringRef name) : Name(name), State(NS_Attrs) {} bool isDoneWithAttrs() const { return State != NS_Attrs; } }; @@ -159,7 +159,7 @@ template <class Impl> struct XMLTypeVisitor { #undef DISPATCH }; -static llvm::StringRef getTypeKindName(Type *T) { +static StringRef getTypeKindName(Type *T) { switch (T->getTypeClass()) { #define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type"; #define ABSTRACT_TYPE(DERIVED, BASE) @@ -172,11 +172,11 @@ static llvm::StringRef getTypeKindName(Type *T) { struct XMLDumper : public XMLDeclVisitor<XMLDumper>, public XMLTypeVisitor<XMLDumper> { - llvm::raw_ostream &out; + raw_ostream &out; ASTContext &Context; - llvm::SmallVector<Node, 16> Stack; + SmallVector<Node, 16> Stack; unsigned Indent; - explicit XMLDumper(llvm::raw_ostream &OS, ASTContext &context) + explicit XMLDumper(raw_ostream &OS, ASTContext &context) : out(OS), Context(context), Indent(0) {} void indent() { @@ -185,7 +185,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } /// Push a new node on the stack. - void push(llvm::StringRef name) { + void push(StringRef name) { if (!Stack.empty()) { assert(Stack.back().isDoneWithAttrs()); if (Stack.back().State == NS_LazyChildren) { @@ -200,7 +200,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } /// Set the given attribute to the given value. - void set(llvm::StringRef attr, llvm::StringRef value) { + void set(StringRef attr, StringRef value) { assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation } @@ -226,7 +226,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, //---- General utilities -------------------------------------------// - void setPointer(llvm::StringRef prop, const void *p) { + void setPointer(StringRef prop, const void *p) { llvm::SmallString<10> buffer; llvm::raw_svector_ostream os(buffer); os << p; @@ -238,11 +238,11 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, setPointer("ptr", p); } - void setInteger(llvm::StringRef prop, const llvm::APSInt &v) { + void setInteger(StringRef prop, const llvm::APSInt &v) { set(prop, v.toString(10)); } - void setInteger(llvm::StringRef prop, unsigned n) { + void setInteger(StringRef prop, unsigned n) { llvm::SmallString<10> buffer; llvm::raw_svector_ostream os(buffer); os << n; @@ -250,7 +250,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, set(prop, buffer); } - void setFlag(llvm::StringRef prop, bool flag) { + void setFlag(StringRef prop, bool flag) { if (flag) set(prop, "true"); } @@ -268,7 +268,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, class TemporaryContainer { XMLDumper &Dumper; public: - TemporaryContainer(XMLDumper &dumper, llvm::StringRef name) + TemporaryContainer(XMLDumper &dumper, StringRef name) : Dumper(dumper) { Dumper.push(name); Dumper.completeAttrs(); @@ -303,7 +303,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, completeAttrs(); pop(); } - void visitDeclRef(llvm::StringRef Name, Decl *D) { + void visitDeclRef(StringRef Name, Decl *D) { TemporaryContainer C(*this, Name); if (D) visitDeclRef(D); } @@ -423,7 +423,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, // LinkageSpecDecl void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) { - llvm::StringRef lang = ""; + StringRef lang = ""; switch (D->getLanguage()) { case LinkageSpecDecl::lang_c: lang = "C"; break; case LinkageSpecDecl::lang_cxx: lang = "C++"; break; @@ -742,8 +742,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, // ObjCClassDecl void visitObjCClassDeclChildren(ObjCClassDecl *D) { - for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I) - visitDeclRef(I->getInterface()); + visitDeclRef(D->getForwardInterfaceDecl()); } // ObjCInterfaceDecl @@ -860,7 +859,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } // ObjCIvarDecl - void setAccessControl(llvm::StringRef prop, ObjCIvarDecl::AccessControl AC) { + void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) { switch (AC) { case ObjCIvarDecl::None: return set(prop, "none"); case ObjCIvarDecl::Private: return set(prop, "private"); @@ -1031,13 +1030,13 @@ void Decl::dumpXML() const { dumpXML(llvm::errs()); } -void Decl::dumpXML(llvm::raw_ostream &out) const { +void Decl::dumpXML(raw_ostream &out) const { XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this)); } #else /* ifndef NDEBUG */ void Decl::dumpXML() const {} -void Decl::dumpXML(llvm::raw_ostream &out) const {} +void Decl::dumpXML(raw_ostream &out) const {} #endif diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 4611ae3..b0bcfe0 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -130,57 +130,6 @@ SourceLocation Expr::getExprLoc() const { // Primary Expressions. //===----------------------------------------------------------------------===// -void ExplicitTemplateArgumentList::initializeFrom( - const TemplateArgumentListInfo &Info) { - LAngleLoc = Info.getLAngleLoc(); - RAngleLoc = Info.getRAngleLoc(); - NumTemplateArgs = Info.size(); - - TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); -} - -void ExplicitTemplateArgumentList::initializeFrom( - const TemplateArgumentListInfo &Info, - bool &Dependent, - bool &InstantiationDependent, - bool &ContainsUnexpandedParameterPack) { - LAngleLoc = Info.getLAngleLoc(); - RAngleLoc = Info.getRAngleLoc(); - NumTemplateArgs = Info.size(); - - TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); - for (unsigned i = 0; i != NumTemplateArgs; ++i) { - Dependent = Dependent || Info[i].getArgument().isDependent(); - InstantiationDependent = InstantiationDependent || - Info[i].getArgument().isInstantiationDependent(); - ContainsUnexpandedParameterPack - = ContainsUnexpandedParameterPack || - Info[i].getArgument().containsUnexpandedParameterPack(); - - new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); - } -} - -void ExplicitTemplateArgumentList::copyInto( - TemplateArgumentListInfo &Info) const { - Info.setLAngleLoc(LAngleLoc); - Info.setRAngleLoc(RAngleLoc); - for (unsigned I = 0; I != NumTemplateArgs; ++I) - 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 sizeFor(Info.size()); -} - /// \brief Compute the type-, value-, and instantiation-dependence of a /// declaration reference /// based on the declaration being referenced. @@ -325,7 +274,8 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, if (InstantiationDependent) setInstantiationDependent(true); } - + DeclRefExprBits.HadMultipleCandidates = 0; + computeDependence(); } @@ -360,7 +310,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, if (FoundD) Size += sizeof(NamedDecl *); if (TemplateArgs) - Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); + Size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs); void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(QualifierLoc, D, NameInfo, FoundD, TemplateArgs, @@ -378,7 +328,7 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, if (HasFoundDecl) Size += sizeof(NamedDecl *); if (HasExplicitTemplateArgs) - Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + Size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(EmptyShell()); @@ -463,7 +413,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { // For incorrect code, there might not be an ObjCInterfaceDecl. Do // a null check to avoid a crash. if (const ObjCInterfaceDecl *ID = MD->getClassInterface()) - Out << ID; + Out << *ID; if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext())) @@ -532,9 +482,8 @@ double FloatingLiteral::getValueAsApproximateDouble() const { return V.convertToDouble(); } -StringLiteral *StringLiteral::Create(ASTContext &C, llvm::StringRef Str, - bool Wide, - bool Pascal, QualType Ty, +StringLiteral *StringLiteral::Create(ASTContext &C, StringRef Str, + StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumStrs) { // Allocate enough space for the StringLiteral plus an array of locations for @@ -549,7 +498,7 @@ StringLiteral *StringLiteral::Create(ASTContext &C, llvm::StringRef Str, memcpy(AStrData, Str.data(), Str.size()); SL->StrData = AStrData; SL->ByteLength = Str.size(); - SL->IsWide = Wide; + SL->Kind = Kind; SL->IsPascal = Pascal; SL->TokLocs[0] = Loc[0]; SL->NumConcatenated = NumStrs; @@ -570,7 +519,7 @@ StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) { return SL; } -void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) { +void StringLiteral::setString(ASTContext &C, StringRef Str) { char *AStrData = new (C, 1) char[Str.size()]; memcpy(AStrData, Str.data(), Str.size()); StrData = AStrData; @@ -587,8 +536,8 @@ void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) { SourceLocation StringLiteral:: getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target) const { - assert(!isWide() && "This doesn't work for wide strings yet"); - + assert(Kind == StringLiteral::Ascii && "This only works for ASCII strings"); + // Loop over all of the tokens in this string until we find the one that // contains the byte we're looking for. unsigned TokNo = 0; @@ -604,7 +553,7 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM, // Re-lex the token to get its length and original spelling. std::pair<FileID, unsigned> LocInfo =SM.getDecomposedLoc(StrTokSpellingLoc); bool Invalid = false; - llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); + StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); if (Invalid) return StrTokSpellingLoc; @@ -647,7 +596,7 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM, /// corresponds to, e.g. "sizeof" or "[pre]++". const char *UnaryOperator::getOpcodeStr(Opcode Op) { switch (Op) { - default: assert(0 && "Unknown unary operator"); + default: llvm_unreachable("Unknown unary operator"); case UO_PostInc: return "++"; case UO_PostDec: return "--"; case UO_PreInc: return "++"; @@ -667,7 +616,7 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) { UnaryOperatorKind UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) { switch (OO) { - default: assert(false && "No unary operator for overloaded function"); + default: llvm_unreachable("No unary operator for overloaded function"); case OO_PlusPlus: return Postfix ? UO_PostInc : UO_PreInc; case OO_MinusMinus: return Postfix ? UO_PostDec : UO_PreDec; case OO_Amp: return UO_AddrOf; @@ -771,7 +720,13 @@ CallExpr::CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, } Decl *CallExpr::getCalleeDecl() { - Expr *CEE = getCallee()->IgnoreParenCasts(); + Expr *CEE = getCallee()->IgnoreParenImpCasts(); + + while (SubstNonTypeTemplateParmExpr *NTTP + = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) { + CEE = NTTP->getReplacement()->IgnoreParenCasts(); + } + // If we're calling a dereference, look at the pointer instead. if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) { if (BO->isPtrMemOp()) @@ -947,7 +902,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, Size += sizeof(MemberNameQualifier); if (targs) - Size += ExplicitTemplateArgumentList::sizeFor(*targs); + Size += ASTTemplateArgumentListInfo::sizeFor(*targs); void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, @@ -1008,6 +963,94 @@ SourceRange MemberExpr::getSourceRange() const { return SourceRange(StartLoc, EndLoc); } +void CastExpr::CheckCastConsistency() const { + switch (getCastKind()) { + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_DerivedToBaseMemberPointer: + case CK_BaseToDerived: + case CK_BaseToDerivedMemberPointer: + assert(!path_empty() && "Cast kind should have a base path!"); + break; + + case CK_CPointerToObjCPointerCast: + assert(getType()->isObjCObjectPointerType()); + assert(getSubExpr()->getType()->isPointerType()); + goto CheckNoBasePath; + + case CK_BlockPointerToObjCPointerCast: + assert(getType()->isObjCObjectPointerType()); + assert(getSubExpr()->getType()->isBlockPointerType()); + goto CheckNoBasePath; + + case CK_BitCast: + // Arbitrary casts to C pointer types count as bitcasts. + // Otherwise, we should only have block and ObjC pointer casts + // here if they stay within the type kind. + if (!getType()->isPointerType()) { + assert(getType()->isObjCObjectPointerType() == + getSubExpr()->getType()->isObjCObjectPointerType()); + assert(getType()->isBlockPointerType() == + getSubExpr()->getType()->isBlockPointerType()); + } + goto CheckNoBasePath; + + case CK_AnyPointerToBlockPointerCast: + assert(getType()->isBlockPointerType()); + assert(getSubExpr()->getType()->isAnyPointerType() && + !getSubExpr()->getType()->isBlockPointerType()); + goto CheckNoBasePath; + + // These should not have an inheritance path. + case CK_Dynamic: + case CK_ToUnion: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_NullToMemberPointer: + case CK_NullToPointer: + case CK_ConstructorConversion: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_ToVoid: + case CK_VectorSplat: + case CK_IntegralCast: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingCast: + case CK_ObjCObjectLValueCast: + case CK_FloatingRealToComplex: + case CK_FloatingComplexToReal: + case CK_FloatingComplexCast: + case CK_FloatingComplexToIntegralComplex: + case CK_IntegralRealToComplex: + case CK_IntegralComplexToReal: + case CK_IntegralComplexCast: + case CK_IntegralComplexToFloatingComplex: + case CK_ARCProduceObject: + case CK_ARCConsumeObject: + case CK_ARCReclaimReturnedObject: + case CK_ARCExtendBlockObject: + assert(!getType()->isBooleanType() && "unheralded conversion to bool"); + goto CheckNoBasePath; + + case CK_Dependent: + case CK_LValueToRValue: + case CK_GetObjCProperty: + case CK_NoOp: + case CK_PointerToBoolean: + case CK_IntegralToBoolean: + case CK_FloatingToBoolean: + case CK_MemberPointerToBoolean: + case CK_FloatingComplexToBoolean: + case CK_IntegralComplexToBoolean: + case CK_LValueBitCast: // -> bool& + case CK_UserDefinedConversion: // operator bool() + CheckNoBasePath: + assert(path_empty() && "Cast kind should not have a base path!"); + break; + } +} + const char *CastExpr::getCastKindName() const { switch (getCastKind()) { case CK_Dependent: @@ -1072,8 +1115,10 @@ const char *CastExpr::getCastKindName() const { return "FloatingToBoolean"; case CK_MemberPointerToBoolean: return "MemberPointerToBoolean"; - case CK_AnyPointerToObjCPointerCast: - return "AnyPointerToObjCPointerCast"; + case CK_CPointerToObjCPointerCast: + return "CPointerToObjCPointerCast"; + case CK_BlockPointerToObjCPointerCast: + return "BlockPointerToObjCPointerCast"; case CK_AnyPointerToBlockPointerCast: return "AnyPointerToBlockPointerCast"; case CK_ObjCObjectLValueCast: @@ -1098,12 +1143,14 @@ const char *CastExpr::getCastKindName() const { return "IntegralComplexCast"; case CK_IntegralComplexToFloatingComplex: return "IntegralComplexToFloatingComplex"; - case CK_ObjCConsumeObject: - return "ObjCConsumeObject"; - case CK_ObjCProduceObject: - return "ObjCProduceObject"; - case CK_ObjCReclaimReturnedObject: - return "ObjCReclaimReturnedObject"; + case CK_ARCConsumeObject: + return "ARCConsumeObject"; + case CK_ARCProduceObject: + return "ARCProduceObject"; + case CK_ARCReclaimReturnedObject: + return "ARCReclaimReturnedObject"; + case CK_ARCExtendBlockObject: + return "ARCCExtendBlockObject"; } llvm_unreachable("Unhandled cast kind!"); @@ -1243,7 +1290,7 @@ const char *BinaryOperator::getOpcodeStr(Opcode Op) { BinaryOperatorKind BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) { switch (OO) { - default: assert(false && "Not an overloadable binary operator"); + default: llvm_unreachable("Not an overloadable binary operator"); case OO_Plus: return BO_Add; case OO_Minus: return BO_Sub; case OO_Star: return BO_Mul; @@ -1491,6 +1538,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, } case CompoundAssignOperatorClass: case VAArgExprClass: + case AtomicExprClass: return false; case ConditionalOperatorClass: { @@ -1525,8 +1573,24 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, R2 = cast<ArraySubscriptExpr>(this)->getRHS()->getSourceRange(); return true; + case CXXOperatorCallExprClass: { + // We warn about operator== and operator!= even when user-defined operator + // overloads as there is no reasonable way to define these such that they + // have non-trivial, desirable side-effects. See the -Wunused-comparison + // warning: these operators are commonly typo'ed, and so warning on them + // provides additional value as well. If this list is updated, + // DiagnoseUnusedComparison should be as well. + const CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(this); + if (Op->getOperator() == OO_EqualEqual || + Op->getOperator() == OO_ExclaimEqual) { + Loc = Op->getOperatorLoc(); + R1 = Op->getSourceRange(); + return true; + } + + // Fallthrough for generic call handling. + } case CallExprClass: - case CXXOperatorCallExprClass: case CXXMemberCallExprClass: { // If this is a direct call, get the callee. const CallExpr *CE = cast<CallExpr>(this); @@ -1666,8 +1730,15 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { ->isOBJCGCCandidate(Ctx); case CStyleCastExprClass: return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx); + case BlockDeclRefExprClass: case DeclRefExprClass: { - const Decl *D = cast<DeclRefExpr>(E)->getDecl(); + + const Decl *D; + if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E)) + D = BDRE->getDecl(); + else + D = cast<DeclRefExpr>(E)->getDecl(); + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasGlobalStorage()) return true; @@ -2024,7 +2095,11 @@ Expr *Expr::IgnoreParenCasts() { E = Materialize->GetTemporaryExpr(); continue; } - + if (SubstNonTypeTemplateParmExpr *NTTP + = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { + E = NTTP->getReplacement(); + continue; + } return E; } } @@ -2058,6 +2133,10 @@ Expr *Expr::IgnoreParenLValueCasts() { = dyn_cast<MaterializeTemporaryExpr>(E)) { E = Materialize->GetTemporaryExpr(); continue; + } else if (SubstNonTypeTemplateParmExpr *NTTP + = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { + E = NTTP->getReplacement(); + continue; } break; } @@ -2092,6 +2171,11 @@ Expr *Expr::IgnoreParenImpCasts() { E = Materialize->GetTemporaryExpr(); continue; } + if (SubstNonTypeTemplateParmExpr *NTTP + = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { + E = NTTP->getReplacement(); + continue; + } return E; } } @@ -2149,6 +2233,12 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { } } + if (SubstNonTypeTemplateParmExpr *NTTP + = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { + E = NTTP->getReplacement(); + continue; + } + return E; } } @@ -2397,7 +2487,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { break; case MaterializeTemporaryExprClass: - return llvm::cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() + return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() ->isConstantInitializer(Ctx, false); } return isEvaluatable(Ctx); @@ -2414,9 +2504,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx, if (isValueDependent()) { switch (NPC) { case NPC_NeverValueDependent: - assert(false && "Unexpected value dependent expression!"); - // If the unthinkable happens, fall through to the safest alternative. - + llvm_unreachable("Unexpected value dependent expression!"); case NPC_ValueDependentIsNull: if (isTypeDependent() || getType()->isIntegralType(Ctx)) return NPCK_ZeroInteger; @@ -2576,7 +2664,7 @@ unsigned ExtVectorElementExpr::getNumElements() const { bool ExtVectorElementExpr::containsDuplicateElements() const { // FIXME: Refactor this code to an accessor on the AST node which returns the // "type" of component access, and share with code below and in Sema. - llvm::StringRef Comp = Accessor->getName(); + StringRef Comp = Accessor->getName(); // Halving swizzles do not contain duplicate elements. if (Comp == "hi" || Comp == "lo" || Comp == "even" || Comp == "odd") @@ -2587,7 +2675,7 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { Comp = Comp.substr(1); for (unsigned i = 0, e = Comp.size(); i != e; ++i) - if (Comp.substr(i + 1).find(Comp[i]) != llvm::StringRef::npos) + if (Comp.substr(i + 1).find(Comp[i]) != StringRef::npos) return true; return false; @@ -2595,8 +2683,8 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { /// getEncodedElementAccess - We encode the fields as a llvm ConstantArray. void ExtVectorElementExpr::getEncodedElementAccess( - llvm::SmallVectorImpl<unsigned> &Elts) const { - llvm::StringRef Comp = Accessor->getName(); + SmallVectorImpl<unsigned> &Elts) const { + StringRef Comp = Accessor->getName(); if (Comp[0] == 's' || Comp[0] == 'S') Comp = Comp.substr(1); @@ -2630,23 +2718,23 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, bool IsInstanceSuper, QualType SuperType, Selector Sel, - SourceLocation SelLoc, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RBracLoc) : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, /*TypeDependent=*/false, /*ValueDependent=*/false, /*InstantiationDependent=*/false, /*ContainsUnexpandedParameterPack=*/false), - NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass), - HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), - SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) + Kind(IsInstanceSuper? SuperInstance : SuperClass), + HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc), + LBracLoc(LBracLoc), RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); setReceiverPointer(SuperType.getAsOpaquePtr()); - if (NumArgs) - memcpy(getArgs(), Args, NumArgs * sizeof(Expr *)); } ObjCMessageExpr::ObjCMessageExpr(QualType T, @@ -2654,33 +2742,22 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SourceLocation LBracLoc, TypeSourceInfo *Receiver, Selector Sel, - SourceLocation SelLoc, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RBracLoc) : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), T->isDependentType(), T->isInstantiationDependentType(), T->containsUnexpandedParameterPack()), - NumArgs(NumArgs), Kind(Class), - HasMethod(Method != 0), IsDelegateInitCall(false), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), - SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) + Kind(Class), + HasMethod(Method != 0), IsDelegateInitCall(false), + LBracLoc(LBracLoc), RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); setReceiverPointer(Receiver); - Expr **MyArgs = getArgs(); - for (unsigned I = 0; I != NumArgs; ++I) { - if (Args[I]->isTypeDependent()) - ExprBits.TypeDependent = true; - if (Args[I]->isValueDependent()) - ExprBits.ValueDependent = true; - if (Args[I]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (Args[I]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - - MyArgs[I] = Args[I]; - } } ObjCMessageExpr::ObjCMessageExpr(QualType T, @@ -2688,23 +2765,31 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SourceLocation LBracLoc, Expr *Receiver, Selector Sel, - SourceLocation SelLoc, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RBracLoc) : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(), Receiver->isTypeDependent(), Receiver->isInstantiationDependent(), Receiver->containsUnexpandedParameterPack()), - NumArgs(NumArgs), Kind(Instance), - HasMethod(Method != 0), IsDelegateInitCall(false), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), - SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) + Kind(Instance), + HasMethod(Method != 0), IsDelegateInitCall(false), + LBracLoc(LBracLoc), RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); setReceiverPointer(Receiver); +} + +void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK) { + setNumArgs(Args.size()); Expr **MyArgs = getArgs(); - for (unsigned I = 0; I != NumArgs; ++I) { + for (unsigned I = 0; I != Args.size(); ++I) { if (Args[I]->isTypeDependent()) ExprBits.TypeDependent = true; if (Args[I]->isValueDependent()) @@ -2716,6 +2801,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, MyArgs[I] = Args[I]; } + + SelLocsKind = SelLocsK; + if (SelLocsK == SelLoc_NonStandard) + std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, @@ -2725,16 +2814,15 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, bool IsInstanceSuper, QualType SuperType, Selector Sel, - SourceLocation SelLoc, + ArrayRef<SourceLocation> SelLocs, ObjCMethodDecl *Method, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RBracLoc) { - unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + - NumArgs * sizeof(Expr *); - void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); + SelectorLocationsKind SelLocsK; + ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, - SuperType, Sel, SelLoc, Method, Args,NumArgs, - RBracLoc); + SuperType, Sel, SelLocs, SelLocsK, + Method, Args, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, @@ -2742,15 +2830,14 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, SourceLocation LBracLoc, TypeSourceInfo *Receiver, Selector Sel, - SourceLocation SelLoc, + ArrayRef<SourceLocation> SelLocs, ObjCMethodDecl *Method, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RBracLoc) { - unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + - NumArgs * sizeof(Expr *); - void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); - return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc, - Method, Args, NumArgs, RBracLoc); + SelectorLocationsKind SelLocsK; + ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, + SelLocs, SelLocsK, Method, Args, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, @@ -2758,25 +2845,50 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, SourceLocation LBracLoc, Expr *Receiver, Selector Sel, - SourceLocation SelLoc, + ArrayRef<SourceLocation> SelLocs, ObjCMethodDecl *Method, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RBracLoc) { - unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + - NumArgs * sizeof(Expr *); - void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); - return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc, - Method, Args, NumArgs, RBracLoc); + SelectorLocationsKind SelLocsK; + ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, + SelLocs, SelLocsK, Method, Args, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, - unsigned NumArgs) { - unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + - NumArgs * sizeof(Expr *); - void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); + unsigned NumArgs, + unsigned NumStoredSelLocs) { + ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs); return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); } +ObjCMessageExpr *ObjCMessageExpr::alloc(ASTContext &C, + ArrayRef<Expr *> Args, + SourceLocation RBraceLoc, + ArrayRef<SourceLocation> SelLocs, + Selector Sel, + SelectorLocationsKind &SelLocsK) { + SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, RBraceLoc); + unsigned NumStoredSelLocs = (SelLocsK == SelLoc_NonStandard) ? SelLocs.size() + : 0; + return alloc(C, Args.size(), NumStoredSelLocs); +} + +ObjCMessageExpr *ObjCMessageExpr::alloc(ASTContext &C, + unsigned NumArgs, + unsigned NumStoredSelLocs) { + unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + + NumArgs * sizeof(Expr *) + NumStoredSelLocs * sizeof(SourceLocation); + return (ObjCMessageExpr *)C.Allocate(Size, + llvm::AlignOf<ObjCMessageExpr>::Alignment); +} + +void ObjCMessageExpr::getSelectorLocs( + SmallVectorImpl<SourceLocation> &SelLocs) const { + for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) + SelLocs.push_back(getSelectorLoc(i)); +} + SourceRange ObjCMessageExpr::getReceiverRange() const { switch (getReceiverKind()) { case Instance: @@ -2830,7 +2942,7 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { return 0; } -llvm::StringRef ObjCBridgedCastExpr::getBridgeKindName() const { +StringRef ObjCBridgedCastExpr::getBridgeKindName() const { switch (getBridgeKind()) { case OBC_Bridge: return "__bridge"; @@ -2844,7 +2956,7 @@ llvm::StringRef ObjCBridgedCastExpr::getBridgeKindName() const { } bool ChooseExpr::isConditionTrue(const ASTContext &C) const { - return getCond()->EvaluateAsInt(C) != 0; + return getCond()->EvaluateKnownConstInt(C) != 0; } ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, @@ -3203,3 +3315,24 @@ BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, ExprBits.ValueDependent = ValueDependent; ExprBits.InstantiationDependent = InstantiationDependent; } + + +AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, + QualType t, AtomicOp op, SourceLocation RP) + : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, + false, false, false, false), + NumSubExprs(nexpr), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) +{ + for (unsigned i = 0; i < nexpr; i++) { + if (args[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i] = args[i]; + } +} diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index f92afff..ad5ec8b 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -49,6 +49,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SourceRange TypeIdParens, Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, Expr **constructorArgs, unsigned numConsArgs, + bool HadMultipleCandidates, FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, QualType ty, TypeSourceInfo *AllocatedTypeInfo, @@ -61,6 +62,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, ty->containsUnexpandedParameterPack()), GlobalNew(globalNew), Initializer(initializer), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), + HadMultipleCandidates(HadMultipleCandidates), SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), Constructor(constructor), AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens), @@ -202,7 +204,7 @@ UnresolvedLookupExpr::Create(ASTContext &C, UnresolvedSetIterator End) { void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + - ExplicitTemplateArgumentList::sizeFor(Args)); + ASTTemplateArgumentListInfo::sizeFor(Args)); return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo, ADL, /*Overload*/ true, &Args, Begin, End, /*StdIsAssociated=*/false); @@ -213,7 +215,7 @@ UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, unsigned NumTemplateArgs) { std::size_t size = sizeof(UnresolvedLookupExpr); if (HasExplicitTemplateArgs) - size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>()); UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell()); @@ -332,7 +334,7 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, bool ContainsUnexpandedParameterPack = ExprBits.ContainsUnexpandedParameterPack; - reinterpret_cast<ExplicitTemplateArgumentList*>(this+1) + reinterpret_cast<ASTTemplateArgumentListInfo*>(this+1) ->initializeFrom(*Args, Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); @@ -347,7 +349,7 @@ DependentScopeDeclRefExpr::Create(ASTContext &C, const TemplateArgumentListInfo *Args) { std::size_t size = sizeof(DependentScopeDeclRefExpr); if (Args) - size += ExplicitTemplateArgumentList::sizeFor(*Args); + size += ASTTemplateArgumentListInfo::sizeFor(*Args); void *Mem = C.Allocate(size); return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc, NameInfo, Args); @@ -359,7 +361,7 @@ DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) { std::size_t size = sizeof(DependentScopeDeclRefExpr); if (HasExplicitTemplateArgs) - size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size); DependentScopeDeclRefExpr *E = new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(), @@ -628,11 +630,13 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, Expr **Args, unsigned NumArgs, SourceRange parenRange, + bool HadMultipleCandidates, bool ZeroInitialization) : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), - Cons, false, Args, NumArgs, ZeroInitialization, + Cons, false, Args, NumArgs, + HadMultipleCandidates, ZeroInitialization, CXXConstructExpr::CK_Complete, parenRange), Type(Type) { } @@ -646,11 +650,13 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, + bool HadMultipleCandidates, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, - Elidable, Args, NumArgs, ZeroInitialization, + Elidable, Args, NumArgs, + HadMultipleCandidates, ZeroInitialization, ConstructKind, ParenRange); } @@ -658,16 +664,18 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool elidable, Expr **args, unsigned numargs, - bool ZeroInitialization, + bool HadMultipleCandidates, + bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenRange) : Expr(SC, T, VK_RValue, OK_Ordinary, T->isDependentType(), T->isDependentType(), T->isInstantiationDependentType(), T->containsUnexpandedParameterPack()), - Constructor(D), Loc(Loc), ParenRange(ParenRange), Elidable(elidable), - ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), - Args(0), NumArgs(numargs) + Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs), + Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), + ZeroInitialization(ZeroInitialization), + ConstructKind(ConstructKind), Args(0) { if (NumArgs) { Args = new (C) Stmt*[NumArgs]; @@ -838,7 +846,7 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, std::size_t size = sizeof(CXXDependentScopeMemberExpr); if (TemplateArgs) - size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); + size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>()); return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, @@ -859,7 +867,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, DeclarationNameInfo()); std::size_t size = sizeof(CXXDependentScopeMemberExpr) + - ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>()); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(), @@ -947,7 +955,7 @@ UnresolvedMemberExpr::Create(ASTContext &C, UnresolvedSetIterator End) { std::size_t size = sizeof(UnresolvedMemberExpr); if (TemplateArgs) - size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); + size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>()); return new (Mem) UnresolvedMemberExpr(C, @@ -961,7 +969,7 @@ UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, unsigned NumTemplateArgs) { std::size_t size = sizeof(UnresolvedMemberExpr); if (HasExplicitTemplateArgs) - size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>()); UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell()); diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index e7888a6..49c6821 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -162,6 +162,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::SubstNonTypeTemplateParmPackExprClass: case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: + case Expr::AtomicExprClass: return Cl::CL_PRValue; // Next come the complicated cases. @@ -393,7 +394,7 @@ static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) { // 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 + // if the result type is an rvalue reference to object type, and a prvalue // otherwise. if (T->isLValueReferenceType()) return Cl::CL_LValue; diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 786155a..df75bc8 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -59,6 +59,8 @@ namespace { EvalInfo(const ASTContext &ctx, Expr::EvalResult &evalresult) : Ctx(ctx), EvalResult(evalresult) {} + + const LangOptions &getLangOpts() { return Ctx.getLangOptions(); } }; struct ComplexValue { @@ -378,18 +380,22 @@ private: RetTy DerivedError(const Expr *E) { return static_cast<Derived*>(this)->Error(E); } + RetTy DerivedValueInitialization(const Expr *E) { + return static_cast<Derived*>(this)->ValueInitialization(E); + } protected: EvalInfo &Info; typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; + RetTy ValueInitialization(const Expr *E) { return DerivedError(E); } + public: ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} RetTy VisitStmt(const Stmt *) { - assert(0 && "Expression evaluator should not be called on stmts"); - return DerivedError(0); + llvm_unreachable("Expression evaluator should not be called on stmts"); } RetTy VisitExpr(const Expr *E) { return DerivedError(E); @@ -436,6 +442,23 @@ public: : DerivedError(E)); return DerivedSuccess(*value, E); } + + RetTy VisitInitListExpr(const InitListExpr *E) { + if (Info.getLangOpts().CPlusPlus0x) { + if (E->getNumInits() == 0) + return DerivedValueInitialization(E); + if (E->getNumInits() == 1) + return StmtVisitorTy::Visit(E->getInit(0)); + } + return DerivedError(E); + } + RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { + return DerivedValueInitialization(E); + } + RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { + return DerivedValueInitialization(E); + } + }; } @@ -447,6 +470,7 @@ namespace { class LValueExprEvaluator : public ExprEvaluatorBase<LValueExprEvaluator, bool> { LValue &Result; + const Decl *PrevDecl; bool Success(const Expr *E) { Result.Base = E; @@ -456,7 +480,7 @@ class LValueExprEvaluator public: LValueExprEvaluator(EvalInfo &info, LValue &Result) : - ExprEvaluatorBaseTy(info), Result(Result) {} + ExprEvaluatorBaseTy(info), Result(Result), PrevDecl(0) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(V); @@ -481,9 +505,13 @@ public: return false; case CK_NoOp: + case CK_LValueBitCast: return Visit(E->getSubExpr()); + + // FIXME: Support CK_DerivedToBase and friends. } } + // FIXME: Missing: __real__, __imag__ }; @@ -501,10 +529,16 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { return Success(E); // Reference parameters can refer to anything even if they have an // "initializer" in the form of a default argument. - if (!isa<ParmVarDecl>(VD)) + if (!isa<ParmVarDecl>(VD)) { // FIXME: Check whether VD might be overridden! + + // Check for recursive initializers of references. + if (PrevDecl == VD) + return Error(E); + PrevDecl = VD; if (const Expr *Init = VD->getAnyInitializer()) return Visit(Init); + } } return ExprEvaluatorBaseTy::VisitDeclRefExpr(E); @@ -585,6 +619,9 @@ public: bool Error(const Stmt *S) { return false; } + bool ValueInitialization(const Expr *E) { + return Success((Expr*)0); + } bool VisitBinaryOperator(const BinaryOperator *E); bool VisitCastExpr(const CastExpr* E); @@ -599,10 +636,8 @@ public: return Success(E); return false; } - bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) - { return Success((Expr*)0); } bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) - { return Success((Expr*)0); } + { return ValueInitialization(E); } // FIXME: Missing: @protocol, @selector }; @@ -667,7 +702,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { case CK_NoOp: case CK_BitCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: return Visit(SubExpr); @@ -761,11 +797,11 @@ namespace { APValue Success(const APValue &V, const Expr *E) { return V; } APValue Error(const Expr *E) { return APValue(); } + APValue ValueInitialization(const Expr *E) + { return GetZeroVector(E->getType()); } APValue VisitUnaryReal(const UnaryOperator *E) { return Visit(E->getSubExpr()); } - APValue VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) - { return GetZeroVector(E->getType()); } APValue VisitCastExpr(const CastExpr* E); APValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); APValue VisitInitListExpr(const InitListExpr *E); @@ -812,7 +848,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { } // Splat and create vector APValue. - llvm::SmallVector<APValue, 4> Elts(NElts, Result); + SmallVector<APValue, 4> Elts(NElts, Result); return APValue(&Elts[0], Elts.size()); } case CK_BitCast: { @@ -829,7 +865,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { assert((EltTy->isIntegerType() || EltTy->isRealFloatingType()) && "Vectors must be composed of ints or floats"); - llvm::SmallVector<APValue, 4> Elts; + SmallVector<APValue, 4> Elts; for (unsigned i = 0; i != NElts; ++i) { APSInt Tmp = Init.extOrTrunc(EltWidth); @@ -862,7 +898,7 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { unsigned NumElements = VT->getNumElements(); QualType EltTy = VT->getElementType(); - llvm::SmallVector<APValue, 4> Elements; + SmallVector<APValue, 4> Elements; // If a vector is initialized with a single element, that value // becomes every element of the vector, not just the first. @@ -926,7 +962,7 @@ VectorExprEvaluator::GetZeroVector(QualType T) { ZeroElement = APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy))); - llvm::SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement); + SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement); return APValue(&Elements[0], Elements.size()); } @@ -999,6 +1035,8 @@ public: return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); } + bool ValueInitialization(const Expr *E) { return Success(0, E); } + //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// @@ -1039,16 +1077,9 @@ public: return Success(E->getValue(), E); } + // Note, GNU defines __null as an integer, not a pointer. bool VisitGNUNullExpr(const GNUNullExpr *E) { - return Success(0, E); - } - - bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { - return Success(0, E); - } - - bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { - return Success(0, E); + return ValueInitialization(E); } bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) { @@ -1072,7 +1103,7 @@ public: bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); - + private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); @@ -1210,7 +1241,7 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E) { else if (ArgTy->isUnionType()) return union_type_class; else // FIXME: offset_type_class, method_type_class, & lang_type_class? - assert(0 && "CallExpr::isBuiltinClassifyType(): unimplemented type"); + llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); return -1; } @@ -1267,7 +1298,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { // If evaluating the argument has side-effects we can't determine // the size of the object and lower it to unknown now. if (E->getArg(0)->HasSideEffects(Info.Ctx)) { - if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1) + if (E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue() <= 1) return Success(-1ULL, E); return Success(0, E); } @@ -1284,8 +1315,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(E->getArg(0)->isEvaluatable(Info.Ctx), E); case Builtin::BI__builtin_eh_return_data_regno: { - int Operand = E->getArg(0)->EvaluateAsInt(Info.Ctx).getZExtValue(); - Operand = Info.Ctx.Target.getEHDataRegisterNumber(Operand); + int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); + Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand); return Success(Operand, E); } @@ -1300,9 +1331,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { = dyn_cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts())) { // The string literal may have embedded null characters. Find the first // one and truncate there. - llvm::StringRef Str = S->getString(); - llvm::StringRef::size_type Pos = Str.find(0); - if (Pos != llvm::StringRef::npos) + StringRef Str = S->getString(); + StringRef::size_type Pos = Str.find(0); + if (Pos != StringRef::npos) Str = Str.substr(0, Pos); return Success(Str.size(), E); @@ -1419,7 +1450,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { switch (E->getOpcode()) { default: - assert(0 && "Invalid binary operator!"); + llvm_unreachable("Invalid binary operator!"); case BO_LT: return Success(CR == APFloat::cmpLessThan, E); case BO_GT: @@ -1801,7 +1832,8 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_VectorSplat: case CK_IntegralToFloating: case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingRealToComplex: @@ -1818,9 +1850,10 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_GetObjCProperty: case CK_LValueBitCast: case CK_UserDefinedConversion: - case CK_ObjCProduceObject: - case CK_ObjCConsumeObject: - case CK_ObjCReclaimReturnedObject: + case CK_ARCProduceObject: + case CK_ARCConsumeObject: + case CK_ARCReclaimReturnedObject: + case CK_ARCExtendBlockObject: return false; case CK_LValueToRValue: @@ -1943,13 +1976,17 @@ public: return false; } + bool ValueInitialization(const Expr *E) { + Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); + return true; + } + bool VisitCallExpr(const CallExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitCastExpr(const CastExpr *E); - bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); @@ -2219,11 +2256,6 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { return false; } -bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { - Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); - return true; -} - //===----------------------------------------------------------------------===// // Complex Evaluation (for float and integer) //===----------------------------------------------------------------------===// @@ -2255,7 +2287,7 @@ public: bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); - // FIXME Missing: ImplicitValueInitExpr + // FIXME Missing: ImplicitValueInitExpr, InitListExpr }; } // end anonymous namespace @@ -2318,16 +2350,18 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingComplexToReal: case CK_FloatingComplexToBoolean: case CK_IntegralComplexToReal: case CK_IntegralComplexToBoolean: - case CK_ObjCProduceObject: - case CK_ObjCConsumeObject: - case CK_ObjCReclaimReturnedObject: + case CK_ARCProduceObject: + case CK_ARCConsumeObject: + case CK_ARCReclaimReturnedObject: + case CK_ARCExtendBlockObject: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -2633,6 +2667,13 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result, return HandleConversionToBool(this, Result, Info); } +bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const { + EvalResult Scratch; + EvalInfo Info(Ctx, Scratch); + + return EvaluateInteger(this, Result, Info) && !Scratch.HasSideEffects; +} + bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); @@ -2671,7 +2712,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { return HasSideEffect(Info).Visit(this); } -APSInt Expr::EvaluateAsInt(const ASTContext &Ctx) const { +APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { EvalResult EvalResult; bool Result = Evaluate(EvalResult, Ctx); (void)Result; @@ -2755,7 +2796,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: - case Expr::InitListExprClass: case Expr::DesignatedInitExprClass: case Expr::ImplicitValueInitExprClass: case Expr::ParenListExprClass: @@ -2800,6 +2840,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::MaterializeTemporaryExprClass: + case Expr::AtomicExprClass: + return ICEDiag(2, E->getLocStart()); + + case Expr::InitListExprClass: + if (Ctx.getLangOptions().CPlusPlus0x) { + const InitListExpr *ILE = cast<InitListExpr>(E); + if (ILE->getNumInits() == 0) + return NoDiag(); + if (ILE->getNumInits() == 1) + return CheckICE(ILE->getInit(0), Ctx); + // Fall through for more than 1 expression. + } return ICEDiag(2, E->getLocStart()); case Expr::SizeOfPackExprClass: @@ -2963,11 +3015,11 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // Evaluate gives an error for undefined Div/Rem, so make sure // we don't evaluate one. if (LHSResult.Val == 0 && RHSResult.Val == 0) { - llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx); + llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) return ICEDiag(1, E->getLocStart()); if (REval.isSigned() && REval.isAllOnesValue()) { - llvm::APSInt LEval = Exp->getLHS()->EvaluateAsInt(Ctx); + llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) return ICEDiag(1, E->getLocStart()); } @@ -2998,11 +3050,11 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // evaluated are not considered. if (Ctx.getLangOptions().CPlusPlus0x && LHSResult.Val == 0) { if (Exp->getOpcode() == BO_LAnd && - Exp->getLHS()->EvaluateAsInt(Ctx) == 0) + Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0) return LHSResult; if (Exp->getOpcode() == BO_LOr && - Exp->getLHS()->EvaluateAsInt(Ctx) != 0) + Exp->getLHS()->EvaluateKnownConstInt(Ctx) != 0) return LHSResult; } @@ -3012,7 +3064,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // to actually check the condition to see whether the side // with the comma is evaluated. if ((Exp->getOpcode() == BO_LAnd) != - (Exp->getLHS()->EvaluateAsInt(Ctx) == 0)) + (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)) return RHSResult; return NoDiag(); } @@ -3031,11 +3083,17 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXConstCastExprClass: case Expr::ObjCBridgedCastExprClass: { const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr(); - if (SubExpr->getType()->isIntegralOrEnumerationType()) + switch (cast<CastExpr>(E)->getCastKind()) { + case CK_LValueToRValue: + case CK_NoOp: + case CK_IntegralToBoolean: + case CK_IntegralCast: return CheckICE(SubExpr, Ctx); - if (isa<FloatingLiteral>(SubExpr->IgnoreParens())) - return NoDiag(); - return ICEDiag(2, E->getLocStart()); + default: + if (isa<FloatingLiteral>(SubExpr->IgnoreParens())) + return NoDiag(); + return ICEDiag(2, E->getLocStart()); + } } case Expr::BinaryConditionalOperatorClass: { const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E); @@ -3045,7 +3103,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (FalseResult.Val == 2) return FalseResult; if (CommonResult.Val == 1) return CommonResult; if (FalseResult.Val == 1 && - Exp->getCommon()->EvaluateAsInt(Ctx) == 0) return NoDiag(); + Exp->getCommon()->EvaluateKnownConstInt(Ctx) == 0) return NoDiag(); return FalseResult; } case Expr::ConditionalOperatorClass: { @@ -3072,7 +3130,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // subexpressions of [...] conditional (5.16) operations that // are not evaluated are not considered bool TrueBranch = Ctx.getLangOptions().CPlusPlus0x - ? Exp->getCond()->EvaluateAsInt(Ctx) != 0 + ? Exp->getCond()->EvaluateKnownConstInt(Ctx) != 0 : false; ICEDiag TrueResult = NoDiag(); if (!Ctx.getLangOptions().CPlusPlus0x || TrueBranch) @@ -3092,7 +3150,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // Rare case where the diagnostics depend on which side is evaluated // Note that if we get here, CondResult is 0, and at least one of // TrueResult and FalseResult is non-zero. - if (Exp->getCond()->EvaluateAsInt(Ctx) == 0) { + if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) { return FalseResult; } return TrueResult; diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp index b96d65a..fd616db 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp @@ -49,12 +49,10 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC, return DeclContext::lookup_result(); } -void ExternalASTSource::MaterializeVisibleDecls(const DeclContext *DC) { } - ExternalLoadResult ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), - llvm::SmallVectorImpl<Decl*> &Result) { + SmallVectorImpl<Decl*> &Result) { return ELR_AlreadyLoaded; } diff --git a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp index c47a9da..b70520f 100644 --- a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp +++ b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp @@ -33,12 +33,12 @@ namespace clang { /// vs. non-virtual bases. class InheritanceHierarchyWriter { ASTContext& Context; - llvm::raw_ostream &Out; + raw_ostream &Out; std::map<QualType, int, QualTypeOrdering> DirectBaseCount; std::set<QualType, QualTypeOrdering> KnownVirtualBases; public: - InheritanceHierarchyWriter(ASTContext& Context, llvm::raw_ostream& Out) + InheritanceHierarchyWriter(ASTContext& Context, raw_ostream& Out) : Context(Context), Out(Out) { } void WriteGraph(QualType Type) { @@ -55,7 +55,7 @@ protected: /// WriteNodeReference - Write out a reference to the given node, /// using a unique identifier for each direct base and for the /// (only) virtual base. - llvm::raw_ostream& WriteNodeReference(QualType Type, bool FromVirtual); + raw_ostream& WriteNodeReference(QualType Type, bool FromVirtual); }; void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) { @@ -120,7 +120,7 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) { /// WriteNodeReference - Write out a reference to the given node, /// using a unique identifier for each direct base and for the /// (only) virtual base. -llvm::raw_ostream& +raw_ostream& InheritanceHierarchyWriter::WriteNodeReference(QualType Type, bool FromVirtual) { QualType CanonType = Context.getCanonicalType(Type); diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index 30aece3..0027dbf 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -53,7 +53,7 @@ public: const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); CharUnits PointerSize = - Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); return Layout.getNonVirtualSize() == PointerSize; } }; diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index ec9863b..acedf70 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -73,7 +73,7 @@ class ItaniumMangleContext : public MangleContext { public: explicit ItaniumMangleContext(ASTContext &Context, - Diagnostic &Diags) + DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { } uint64_t getAnonymousStructId(const TagDecl *TD) { @@ -92,30 +92,30 @@ public: /// @{ bool shouldMangleDeclName(const NamedDecl *D); - void mangleName(const NamedDecl *D, llvm::raw_ostream &); + void mangleName(const NamedDecl *D, raw_ostream &); void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, - llvm::raw_ostream &); + raw_ostream &); void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThisAdjustment &ThisAdjustment, - llvm::raw_ostream &); + raw_ostream &); void mangleReferenceTemporary(const VarDecl *D, - llvm::raw_ostream &); + raw_ostream &); void mangleCXXVTable(const CXXRecordDecl *RD, - llvm::raw_ostream &); + raw_ostream &); void mangleCXXVTT(const CXXRecordDecl *RD, - llvm::raw_ostream &); + raw_ostream &); void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, const CXXRecordDecl *Type, - llvm::raw_ostream &); - void mangleCXXRTTI(QualType T, llvm::raw_ostream &); - void mangleCXXRTTIName(QualType T, llvm::raw_ostream &); + raw_ostream &); + void mangleCXXRTTI(QualType T, raw_ostream &); + void mangleCXXRTTIName(QualType T, raw_ostream &); void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - llvm::raw_ostream &); + raw_ostream &); void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - llvm::raw_ostream &); + raw_ostream &); - void mangleItaniumGuardVariable(const VarDecl *D, llvm::raw_ostream &); + void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &); void mangleInitDiscriminator() { Discriminator = 0; @@ -136,7 +136,7 @@ public: /// CXXNameMangler - Manage the mangling of a single name. class CXXNameMangler { ItaniumMangleContext &Context; - llvm::raw_ostream &Out; + raw_ostream &Out; /// The "structor" is the top-level declaration being mangled, if /// that's not a template specialization; otherwise it's the pattern @@ -191,7 +191,7 @@ class CXXNameMangler { ASTContext &getASTContext() const { return Context.getASTContext(); } public: - CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, const NamedDecl *D = 0) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0), SeqID(0) { @@ -199,11 +199,11 @@ public: assert(!D || (!isa<CXXDestructorDecl>(D) && !isa<CXXConstructorDecl>(D))); } - CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, const CXXConstructorDecl *D, CXXCtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } - CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } @@ -219,9 +219,9 @@ public: free(result); } #endif - llvm::raw_ostream &getStream() { return Out; } + raw_ostream &getStream() { return Out; } - void mangle(const NamedDecl *D, llvm::StringRef Prefix = "_Z"); + void mangle(const NamedDecl *D, StringRef Prefix = "_Z"); void mangleCallOffset(int64_t NonVirtual, int64_t Virtual); void mangleNumber(const llvm::APSInt &I); void mangleNumber(int64_t Number); @@ -310,7 +310,7 @@ private: void mangleCXXCtorType(CXXCtorType T); void mangleCXXDtorType(CXXDtorType T); - void mangleTemplateArgs(const ExplicitTemplateArgumentList &TemplateArgs); + void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs); void mangleTemplateArgs(TemplateName Template, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); @@ -385,7 +385,7 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { return true; } -void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) { +void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { // Any decl can be declared with __asm("foo") on it, and this takes precedence // over all other naming in the .o file. if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { @@ -397,8 +397,8 @@ void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) { // llvm mangler on ELF is a nop, so we can just avoid adding the \01 // marker. We also avoid adding the marker if this is an alias for an // LLVM intrinsic. - llvm::StringRef UserLabelPrefix = - getASTContext().Target.getUserLabelPrefix(); + StringRef UserLabelPrefix = + getASTContext().getTargetInfo().getUserLabelPrefix(); if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm.")) Out << '\01'; // LLVM IR Marker for __asm("foo") @@ -788,6 +788,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + case Type::Atomic: llvm_unreachable("type is illegal as a nested name specifier"); case Type::SubstTemplateTypeParmPack: @@ -1069,8 +1070,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - assert(false && "Can't mangle Objective-C selector names here!"); - break; + llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: if (ND == Structor) @@ -1124,8 +1124,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; case DeclarationName::CXXUsingDirective: - assert(false && "Can't mangle a using directive name!"); - break; + llvm_unreachable("Can't mangle a using directive name!"); } } @@ -1512,8 +1511,7 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { case OO_None: case NUM_OVERLOADED_OPERATORS: - assert(false && "Not an overloaded operator"); - break; + llvm_unreachable("Not an overloaded operator"); } } @@ -1538,7 +1536,7 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { Out << 'U' << ASString.size() << ASString; } - llvm::StringRef LifetimeName; + StringRef LifetimeName; switch (Quals.getObjCLifetime()) { // Objective-C ARC Extension: // @@ -1706,7 +1704,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits) // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits) // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits) - // UNSUPPORTED: ::= Dh # IEEE 754r half-precision floating point (16 bits) + // ::= Dh # IEEE 754r half-precision floating point (16 bits) // ::= Di # char32_t // ::= Ds # char16_t // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) @@ -1731,6 +1729,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Long: Out << 'l'; break; case BuiltinType::LongLong: Out << 'x'; break; case BuiltinType::Int128: Out << 'n'; break; + case BuiltinType::Half: Out << "Dh"; break; case BuiltinType::Float: Out << 'f'; break; case BuiltinType::Double: Out << 'd'; break; case BuiltinType::LongDouble: Out << 'e'; break; @@ -2114,6 +2113,13 @@ void CXXNameMangler::mangleType(const AutoType *T) { mangleType(D); } +void CXXNameMangler::mangleType(const AtomicType *T) { + // <type> ::= U <source-name> <type> # vendor extended type qualifier + // (Until there's a standardized mangling...) + Out << "U7_Atomic"; + mangleType(T->getValueType()); +} + void CXXNameMangler::mangleIntegerLiteral(QualType T, const llvm::APSInt &Value) { // <expr-primary> ::= L <type> <value number> E # integer literal @@ -2250,10 +2256,11 @@ recurse: case Expr::CXXNoexceptExprClass: case Expr::CUDAKernelCallExprClass: case Expr::AsTypeExprClass: + case Expr::AtomicExprClass: { // As bad as this diagnostic is, it's better than crashing. - Diagnostic &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot yet mangle expression type %0"); Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName() << E->getSourceRange(); @@ -2262,9 +2269,9 @@ recurse: // Even gcc-4.5 doesn't mangle this. case Expr::BinaryConditionalOperatorClass: { - Diagnostic &Diags = Context.getDiags(); + DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = - Diags.getCustomDiagID(Diagnostic::Error, + Diags.getCustomDiagID(DiagnosticsEngine::Error, "?: operator with omitted middle operand cannot be mangled"); Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName() << E->getSourceRange(); @@ -2411,7 +2418,8 @@ recurse: QualType T = (ImplicitlyConvertedToType.isNull() || !ImplicitlyConvertedToType->isIntegerType())? SAE->getType() : ImplicitlyConvertedToType; - mangleIntegerLiteral(T, SAE->EvaluateAsInt(Context.getASTContext())); + llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext()); + mangleIntegerLiteral(T, V); break; } @@ -2423,8 +2431,8 @@ recurse: Out << 'a'; break; case UETT_VecStep: - Diagnostic &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot yet mangle vec_step expression"); Diags.Report(DiagID); return; @@ -2526,7 +2534,7 @@ recurse: case Expr::ObjCBridgedCastExprClass: { // Mangle ownership casts as a vendor extended operator __bridge, // __bridge_transfer, or __bridge_retain. - llvm::StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName(); + StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName(); Out << "v1U" << Kind.size() << Kind; } // Fall through to mangle the cast itself. @@ -2817,7 +2825,7 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { } void CXXNameMangler::mangleTemplateArgs( - const ExplicitTemplateArgumentList &TemplateArgs) { + const ASTTemplateArgumentListInfo &TemplateArgs) { // <template-args> ::= I <template-arg>+ E Out << 'I'; for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i) @@ -3021,7 +3029,7 @@ bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) { } Out << 'S' - << llvm::StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr) + << StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr) << '_'; } @@ -3196,7 +3204,7 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { /// emit the identifier of the declaration (\c D->getIdentifier()) as its /// name. void ItaniumMangleContext::mangleName(const NamedDecl *D, - llvm::raw_ostream &Out) { + raw_ostream &Out) { assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) && "Invalid mangleName() call, argument is not a variable or function!"); assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) && @@ -3212,21 +3220,21 @@ void ItaniumMangleContext::mangleName(const NamedDecl *D, void ItaniumMangleContext::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - llvm::raw_ostream &Out) { + raw_ostream &Out) { CXXNameMangler Mangler(*this, Out, D, Type); Mangler.mangle(D); } void ItaniumMangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - llvm::raw_ostream &Out) { + raw_ostream &Out) { CXXNameMangler Mangler(*this, Out, D, Type); Mangler.mangle(D); } void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // <special-name> ::= T <call-offset> <base encoding> // # base is the nominal target function of thunk // <special-name> ::= Tc <call-offset> <call-offset> <base encoding> @@ -3256,7 +3264,7 @@ void ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThisAdjustment &ThisAdjustment, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // <special-name> ::= T <call-offset> <base encoding> // # base is the nominal target function of thunk CXXNameMangler Mangler(*this, Out, DD, Type); @@ -3272,7 +3280,7 @@ ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, /// mangleGuardVariable - Returns the mangled name for a guard variable /// for the passed in VarDecl. void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // <special-name> ::= GV <object name> # Guard variable for one-time // # initialization CXXNameMangler Mangler(*this, Out); @@ -3281,7 +3289,7 @@ void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D, } void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // We match the GCC mangling here. // <special-name> ::= GR <object name> CXXNameMangler Mangler(*this, Out); @@ -3290,7 +3298,7 @@ void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D, } void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // <special-name> ::= TV <type> # virtual table CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTV"; @@ -3298,7 +3306,7 @@ void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD, } void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // <special-name> ::= TT <type> # VTT structure CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTT"; @@ -3308,7 +3316,7 @@ void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD, void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, const CXXRecordDecl *Type, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // <special-name> ::= TC <type> <offset number> _ <base type> CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTC"; @@ -3319,7 +3327,7 @@ void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, } void ItaniumMangleContext::mangleCXXRTTI(QualType Ty, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // <special-name> ::= TI <type> # typeinfo structure assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers"); CXXNameMangler Mangler(*this, Out); @@ -3328,7 +3336,7 @@ void ItaniumMangleContext::mangleCXXRTTI(QualType Ty, } void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty, - llvm::raw_ostream &Out) { + raw_ostream &Out) { // <special-name> ::= TS <type> # typeinfo name (null terminated byte string) CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTS"; @@ -3336,6 +3344,6 @@ void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty, } MangleContext *clang::createItaniumMangleContext(ASTContext &Context, - Diagnostic &Diags) { + DiagnosticsEngine &Diags) { return new ItaniumMangleContext(Context, Diags); } diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp index c3f3b11..5cb8f47 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -37,9 +37,9 @@ using namespace clang; namespace { static void mangleFunctionBlock(MangleContext &Context, - llvm::StringRef Outer, + StringRef Outer, const BlockDecl *BD, - llvm::raw_ostream &Out) { + raw_ostream &Out) { Out << "__" << Outer << "_block_invoke_" << Context.getBlockId(BD, true); } @@ -60,13 +60,13 @@ static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) { } void MangleContext::mangleGlobalBlock(const BlockDecl *BD, - llvm::raw_ostream &Out) { + raw_ostream &Out) { Out << "__block_global_" << getBlockId(BD, false); } void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, const BlockDecl *BD, - llvm::raw_ostream &ResStream) { + raw_ostream &ResStream) { checkMangleDC(CD, BD); llvm::SmallString<64> Buffer; llvm::raw_svector_ostream Out(Buffer); @@ -77,7 +77,7 @@ void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, CXXDtorType DT, const BlockDecl *BD, - llvm::raw_ostream &ResStream) { + raw_ostream &ResStream) { checkMangleDC(DD, BD); llvm::SmallString<64> Buffer; llvm::raw_svector_ostream Out(Buffer); @@ -87,7 +87,7 @@ void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, } void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, - llvm::raw_ostream &Out) { + raw_ostream &Out) { assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC)); checkMangleDC(DC, BD); @@ -113,7 +113,7 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, } void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, - llvm::raw_ostream &Out) { + raw_ostream &Out) { llvm::SmallString<64> Name; llvm::raw_svector_ostream OS(Name); @@ -129,7 +129,7 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, } void MangleContext::mangleBlock(const BlockDecl *BD, - llvm::raw_ostream &Out) { + raw_ostream &Out) { const DeclContext *DC = BD->getDeclContext(); while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) DC = DC->getParent(); diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp index 206f6dd..f33d6fe 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp @@ -30,7 +30,7 @@ public: unsigned getMemberPointerSize(const MemberPointerType *MPT) const; CallingConv getDefaultMethodCallConv() const { - if (Context.Target.getTriple().getArch() == llvm::Triple::x86) + if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) return CC_X86ThisCall; else return CC_C; @@ -45,7 +45,7 @@ public: // In the Microsoft ABI, classes can have one or two vtable pointers. CharUnits PointerSize = - Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); return Layout.getNonVirtualSize() == PointerSize || Layout.getNonVirtualSize() == PointerSize * 2; } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 4f920f9..1515db4 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -29,15 +29,15 @@ namespace { /// Microsoft Visual C++ ABI. class MicrosoftCXXNameMangler { MangleContext &Context; - llvm::raw_ostream &Out; + raw_ostream &Out; ASTContext &getASTContext() const { return Context.getASTContext(); } public: - MicrosoftCXXNameMangler(MangleContext &C, llvm::raw_ostream &Out_) + MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_) : Context(C), Out(Out_) { } - void mangle(const NamedDecl *D, llvm::StringRef Prefix = "?"); + void mangle(const NamedDecl *D, StringRef Prefix = "?"); void mangleName(const NamedDecl *ND); void mangleFunctionEncoding(const FunctionDecl *FD); void mangleVariableEncoding(const VarDecl *VD); @@ -78,30 +78,30 @@ private: class MicrosoftMangleContext : public MangleContext { public: MicrosoftMangleContext(ASTContext &Context, - Diagnostic &Diags) : MangleContext(Context, Diags) { } + DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { } virtual bool shouldMangleDeclName(const NamedDecl *D); - virtual void mangleName(const NamedDecl *D, llvm::raw_ostream &Out); + virtual void mangleName(const NamedDecl *D, raw_ostream &Out); virtual void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, - llvm::raw_ostream &); + raw_ostream &); virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThisAdjustment &ThisAdjustment, - llvm::raw_ostream &); + raw_ostream &); virtual void mangleCXXVTable(const CXXRecordDecl *RD, - llvm::raw_ostream &); + raw_ostream &); virtual void mangleCXXVTT(const CXXRecordDecl *RD, - llvm::raw_ostream &); + raw_ostream &); virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, const CXXRecordDecl *Type, - llvm::raw_ostream &); - virtual void mangleCXXRTTI(QualType T, llvm::raw_ostream &); - virtual void mangleCXXRTTIName(QualType T, llvm::raw_ostream &); + raw_ostream &); + virtual void mangleCXXRTTI(QualType T, raw_ostream &); + virtual void mangleCXXRTTIName(QualType T, raw_ostream &); virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - llvm::raw_ostream &); + raw_ostream &); virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - llvm::raw_ostream &); + raw_ostream &); virtual void mangleReferenceTemporary(const clang::VarDecl *, - llvm::raw_ostream &); + raw_ostream &); }; } @@ -154,7 +154,7 @@ bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) { } void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, - llvm::StringRef Prefix) { + StringRef Prefix) { // MSVC doesn't mangle C++ names the same way it mangles extern "C" names. // Therefore it's really important that we don't decorate the // name with leading underscores or leading/trailing at signs. So, emit a @@ -332,16 +332,13 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - assert(false && "Can't mangle Objective-C selector names here!"); - break; + llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: - assert(false && "Can't mangle constructors yet!"); - break; + llvm_unreachable("Can't mangle constructors yet!"); case DeclarationName::CXXDestructorName: - assert(false && "Can't mangle destructors yet!"); - break; + llvm_unreachable("Can't mangle destructors yet!"); case DeclarationName::CXXConversionFunctionName: // <operator-name> ::= ?B # (cast) @@ -355,12 +352,10 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::CXXLiteralOperatorName: // FIXME: Was this added in VS2010? Does MS even know how to mangle this? - assert(false && "Don't know how to mangle literal operators yet!"); - break; + llvm_unreachable("Don't know how to mangle literal operators yet!"); case DeclarationName::CXXUsingDirective: - assert(false && "Can't mangle a using directive name!"); - break; + llvm_unreachable("Can't mangle a using directive name!"); } } @@ -513,13 +508,11 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO) { case OO_Array_Delete: Out << "?_V"; break; case OO_Conditional: - assert(false && "Don't know how to mangle ?:"); - break; + llvm_unreachable("Don't know how to mangle ?:"); case OO_None: case NUM_OVERLOADED_OPERATORS: - assert(false && "Not an overloaded operator"); - break; + llvm_unreachable("Not an overloaded operator"); } } @@ -712,18 +705,17 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Dependent: case BuiltinType::UnknownAny: case BuiltinType::BoundMember: - assert(false && + llvm_unreachable( "Overloaded and dependent types shouldn't get to name mangling"); - break; case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break; case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break; case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break; case BuiltinType::Char16: case BuiltinType::Char32: + case BuiltinType::Half: case BuiltinType::NullPtr: - assert(false && "Don't know how to mangle this type"); - break; + llvm_unreachable("Don't know how to mangle this type"); } } @@ -869,7 +861,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T, CC = IsInstMethod ? getASTContext().getDefaultMethodCallConv() : CC_C; switch (CC) { default: - assert(0 && "Unsupported CC for mangling"); + llvm_unreachable("Unsupported CC for mangling"); case CC_Default: case CC_C: Out << 'A'; break; case CC_X86Pascal: Out << 'C'; break; @@ -890,7 +882,7 @@ void MicrosoftCXXNameMangler::mangleThrowSpecification( } void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T) { - assert(false && "Don't know how to mangle UnresolvedUsingTypes yet!"); + llvm_unreachable("Don't know how to mangle UnresolvedUsingTypes yet!"); } // <type> ::= <union-type> | <struct-type> | <class-type> | <enum-type> @@ -954,7 +946,7 @@ void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T) { mangleType(static_cast<const ArrayType *>(T), false); } void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) { - llvm::SmallVector<llvm::APInt, 3> Dimensions; + SmallVector<llvm::APInt, 3> Dimensions; for (;;) { if (ElementTy->isConstantArrayType()) { const ConstantArrayType *CAT = @@ -962,10 +954,10 @@ void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) { Dimensions.push_back(CAT->getSize()); ElementTy = CAT->getElementType(); } else if (ElementTy->isVariableArrayType()) { - assert(false && "Don't know how to mangle VLAs!"); + llvm_unreachable("Don't know how to mangle VLAs!"); } else if (ElementTy->isDependentSizedArrayType()) { // The dependent expression has to be folded into a constant (TODO). - assert(false && "Don't know how to mangle dependent-sized arrays!"); + llvm_unreachable("Don't know how to mangle dependent-sized arrays!"); } else if (ElementTy->isIncompleteArrayType()) continue; else break; } @@ -999,12 +991,12 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T) { } void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T) { - assert(false && "Don't know how to mangle TemplateTypeParmTypes yet!"); + llvm_unreachable("Don't know how to mangle TemplateTypeParmTypes yet!"); } void MicrosoftCXXNameMangler::mangleType( const SubstTemplateTypeParmPackType *T) { - assert(false && + llvm_unreachable( "Don't know how to mangle SubstTemplateTypeParmPackTypes yet!"); } @@ -1045,21 +1037,22 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T) { } void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T) { - assert(false && "Don't know how to mangle RValueReferenceTypes yet!"); + llvm_unreachable("Don't know how to mangle RValueReferenceTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const ComplexType *T) { - assert(false && "Don't know how to mangle ComplexTypes yet!"); + llvm_unreachable("Don't know how to mangle ComplexTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const VectorType *T) { - assert(false && "Don't know how to mangle VectorTypes yet!"); + llvm_unreachable("Don't know how to mangle VectorTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T) { - assert(false && "Don't know how to mangle ExtVectorTypes yet!"); + llvm_unreachable("Don't know how to mangle ExtVectorTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T) { - assert(false && "Don't know how to mangle DependentSizedExtVectorTypes yet!"); + llvm_unreachable( + "Don't know how to mangle DependentSizedExtVectorTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T) { @@ -1080,49 +1073,53 @@ void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T) { } void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T) { - assert(false && "Don't know how to mangle InjectedClassNameTypes yet!"); + llvm_unreachable("Don't know how to mangle InjectedClassNameTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T) { - assert(false && "Don't know how to mangle TemplateSpecializationTypes yet!"); + llvm_unreachable("Don't know how to mangle TemplateSpecializationTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T) { - assert(false && "Don't know how to mangle DependentNameTypes yet!"); + llvm_unreachable("Don't know how to mangle DependentNameTypes yet!"); } void MicrosoftCXXNameMangler::mangleType( const DependentTemplateSpecializationType *T) { - assert(false && + llvm_unreachable( "Don't know how to mangle DependentTemplateSpecializationTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T) { - assert(false && "Don't know how to mangle PackExpansionTypes yet!"); + llvm_unreachable("Don't know how to mangle PackExpansionTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T) { - assert(false && "Don't know how to mangle TypeOfTypes yet!"); + llvm_unreachable("Don't know how to mangle TypeOfTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T) { - assert(false && "Don't know how to mangle TypeOfExprTypes yet!"); + llvm_unreachable("Don't know how to mangle TypeOfExprTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T) { - assert(false && "Don't know how to mangle DecltypeTypes yet!"); + llvm_unreachable("Don't know how to mangle DecltypeTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T) { - assert(false && "Don't know how to mangle UnaryTransformationTypes yet!"); + llvm_unreachable("Don't know how to mangle UnaryTransformationTypes yet!"); } void MicrosoftCXXNameMangler::mangleType(const AutoType *T) { - assert(false && "Don't know how to mangle AutoTypes yet!"); + llvm_unreachable("Don't know how to mangle AutoTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const AtomicType *T) { + llvm_unreachable("Don't know how to mangle AtomicTypes yet!"); } void MicrosoftMangleContext::mangleName(const NamedDecl *D, - llvm::raw_ostream &Out) { + raw_ostream &Out) { assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) && "Invalid mangleName() call, argument is not a variable or function!"); assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) && @@ -1137,53 +1134,53 @@ void MicrosoftMangleContext::mangleName(const NamedDecl *D, } void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, - llvm::raw_ostream &) { - assert(false && "Can't yet mangle thunks!"); + raw_ostream &) { + llvm_unreachable("Can't yet mangle thunks!"); } void MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThisAdjustment &, - llvm::raw_ostream &) { - assert(false && "Can't yet mangle destructor thunks!"); + raw_ostream &) { + llvm_unreachable("Can't yet mangle destructor thunks!"); } void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD, - llvm::raw_ostream &) { - assert(false && "Can't yet mangle virtual tables!"); + raw_ostream &) { + llvm_unreachable("Can't yet mangle virtual tables!"); } void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD, - llvm::raw_ostream &) { + raw_ostream &) { llvm_unreachable("The MS C++ ABI does not have virtual table tables!"); } void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, const CXXRecordDecl *Type, - llvm::raw_ostream &) { + raw_ostream &) { llvm_unreachable("The MS C++ ABI does not have constructor vtables!"); } void MicrosoftMangleContext::mangleCXXRTTI(QualType T, - llvm::raw_ostream &) { - assert(false && "Can't yet mangle RTTI!"); + raw_ostream &) { + llvm_unreachable("Can't yet mangle RTTI!"); } void MicrosoftMangleContext::mangleCXXRTTIName(QualType T, - llvm::raw_ostream &) { - assert(false && "Can't yet mangle RTTI names!"); + raw_ostream &) { + llvm_unreachable("Can't yet mangle RTTI names!"); } void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - llvm::raw_ostream &) { - assert(false && "Can't yet mangle constructors!"); + raw_ostream &) { + llvm_unreachable("Can't yet mangle constructors!"); } void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - llvm::raw_ostream &) { - assert(false && "Can't yet mangle destructors!"); + raw_ostream &) { + llvm_unreachable("Can't yet mangle destructors!"); } void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *, - llvm::raw_ostream &) { - assert(false && "Can't yet mangle reference temporaries!"); + raw_ostream &) { + llvm_unreachable("Can't yet mangle reference temporaries!"); } MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context, - Diagnostic &Diags) { + DiagnosticsEngine &Diags) { return new MicrosoftMangleContext(Context, Diags); } diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index f6d4f25..1ff2e71 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -218,7 +218,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const { /// \brief Print this nested name specifier to the given output /// stream. void -NestedNameSpecifier::print(llvm::raw_ostream &OS, +NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy) const { if (getPrefix()) getPrefix()->print(OS, Policy); @@ -569,7 +569,7 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, // Construct bogus (but well-formed) source information for the // nested-name-specifier. BufferSize = 0; - llvm::SmallVector<NestedNameSpecifier *, 4> Stack; + SmallVector<NestedNameSpecifier *, 4> Stack; for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) Stack.push_back(NNS); while (!Stack.empty()) { diff --git a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp index b7b2005..5eef83a 100644 --- a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp @@ -66,6 +66,14 @@ Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const { return S; } +Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const { + do { + S = getParent(S); + } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S); + + return S; +} + Stmt *ParentMap::getOuterParenParent(Stmt *S) const { Stmt *Paren = 0; while (isa<ParenExpr>(S)) { diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp index 035c48f..ccc591a 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp @@ -13,6 +13,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/RecordLayout.h" +#include "clang/Basic/TargetInfo.h" using namespace clang; @@ -42,7 +43,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, // Constructor for C++ records. ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, - CharUnits datasize, + CharUnits vbptroffset, CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount, CharUnits nonvirtualsize, @@ -67,15 +68,20 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject; CXXInfo->BaseOffsets = BaseOffsets; CXXInfo->VBaseOffsets = VBaseOffsets; + CXXInfo->VBPtrOffset = vbptroffset; #ifndef NDEBUG if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) { - if (isPrimaryBaseVirtual()) + if (isPrimaryBaseVirtual()) { + // Microsoft ABI doesn't have primary virtual base + if (Ctx.getTargetInfo().getCXXABI() != CXXABI_Microsoft) { assert(getVBaseClassOffset(PrimaryBase).isZero() && "Primary virtual base must be at offset 0!"); - else + } + } else { assert(getBaseClassOffsetInBits(PrimaryBase) == 0 && "Primary base must be at offset 0!"); + } } #endif } diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index 5636a6f..bbd3fc0 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -44,7 +44,7 @@ struct BaseSubobjectInfo { bool IsVirtual; /// Bases - Information about the base subobjects. - llvm::SmallVector<BaseSubobjectInfo*, 4> Bases; + SmallVector<BaseSubobjectInfo*, 4> Bases; /// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base /// of this base info (if one exists). @@ -64,7 +64,7 @@ class EmptySubobjectMap { const CXXRecordDecl *Class; /// EmptyClassOffsets - A map from offsets to empty record decls. - typedef llvm::SmallVector<const CXXRecordDecl *, 1> ClassVectorTy; + typedef SmallVector<const CXXRecordDecl *, 1> ClassVectorTy; typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy; EmptyClassOffsetsMapTy EmptyClassOffsets; @@ -556,7 +556,7 @@ protected: /// \brief The alignment if attribute packed is not used. CharUnits UnpackedAlignment; - llvm::SmallVector<uint64_t, 16> FieldOffsets; + SmallVector<uint64_t, 16> FieldOffsets; /// Packed - Whether the record is packed or not. unsigned Packed : 1; @@ -592,6 +592,9 @@ protected: /// out is virtual. bool PrimaryBaseIsVirtual; + /// VBPtrOffset - Virtual base table offset. Only for MS layout. + CharUnits VBPtrOffset; + typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; /// Bases - base classes and their offsets in the record. @@ -613,16 +616,17 @@ protected: llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases; RecordLayoutBuilder(const ASTContext &Context, EmptySubobjectMap - *EmptySubobjects) + *EmptySubobjects, CharUnits Alignment) : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), - Alignment(CharUnits::One()), UnpackedAlignment(Alignment), + Alignment(Alignment), UnpackedAlignment(Alignment), Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false), UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()), DataSize(0), NonVirtualSize(CharUnits::Zero()), NonVirtualAlignment(CharUnits::One()), ZeroLengthBitfield(0), PrimaryBase(0), - PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { } + PrimaryBaseIsVirtual(false), VBPtrOffset(CharUnits::fromQuantity(-1)), + FirstNearlyEmptyVBase(0) { } void Layout(const RecordDecl *D); void Layout(const CXXRecordDecl *D); @@ -633,6 +637,8 @@ protected: void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize, bool FieldPacked, const FieldDecl *D); void LayoutBitField(const FieldDecl *D); + void MSLayoutVirtualBases(const CXXRecordDecl *RD); + void MSLayout(const CXXRecordDecl *RD); /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects. llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator; @@ -663,7 +669,7 @@ protected: void SelectPrimaryVBase(const CXXRecordDecl *RD); - virtual CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const; + CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const; /// LayoutNonVirtualBases - Determines the primary base class (if any) and /// lays it out. Will then proceed to lay out all non-virtual base clasess. @@ -713,6 +719,8 @@ protected: void setSize(CharUnits NewSize) { Size = Context.toBits(NewSize); } void setSize(uint64_t NewSize) { Size = NewSize; } + CharUnits getAligment() const { return Alignment; } + CharUnits getDataSize() const { assert(DataSize % Context.getCharWidth() == 0); return Context.toCharUnitsFromBits(DataSize); @@ -722,6 +730,11 @@ protected: void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); } void setDataSize(uint64_t NewSize) { DataSize = NewSize; } + bool HasVBPtr(const CXXRecordDecl *RD) const; + bool HasNewVirtualFunction(const CXXRecordDecl *RD) const; + + /// Add vbptr or vfptr to layout. + void AddVPointer(); RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT @@ -729,6 +742,8 @@ public: static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD); virtual ~RecordLayoutBuilder() { } + + CharUnits GetVBPtrOffset() const { return VBPtrOffset; } }; } // end anonymous namespace @@ -765,7 +780,7 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { CharUnits RecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const { - return Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); + return Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); } /// DeterminePrimaryBase - Determine the primary base of the given class. @@ -825,7 +840,7 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { setDataSize(getSize()); CharUnits UnpackedBaseAlign = - Context.toCharUnitsFromBits(Context.Target.getPointerAlign(0)); + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0)); CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign; // The maximum field alignment overrides base align. @@ -1046,6 +1061,45 @@ RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, } } +void RecordLayoutBuilder::AddVPointer() { + CharUnits PtrWidth = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); + setSize(getSize() + PtrWidth); + setDataSize(getSize()); + + if (Alignment > PtrWidth) { + setSize(getSize() + (Alignment - PtrWidth)); + setDataSize(getSize()); + } +} + +bool +RecordLayoutBuilder::HasNewVirtualFunction(const CXXRecordDecl *RD) const { + for (CXXRecordDecl::method_iterator method = RD->method_begin(); + method != RD->method_end(); + ++method) { + if (method->isVirtual() && + !method->size_overridden_methods()) { + return true; + } + } + return false; +} + +bool +RecordLayoutBuilder::HasVBPtr(const CXXRecordDecl *RD) const { + if (!RD->getNumBases()) + return false; + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + if (!I->isVirtual()) { + return false; + } + } + return true; +} + void RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass) { @@ -1157,6 +1211,11 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) { IsMsStruct = D->hasAttr<MsStructAttr>(); + // Honor the default struct packing maximum alignment flag. + if (unsigned DefaultMaxFieldAlignment = Context.getLangOptions().PackStruct) { + MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment); + } + // mac68k alignment supersedes maximum field alignment and attribute aligned, // and forces all structures to have 2-byte alignment. The IBM docs on it // allude to additional (more complicated) semantics, especially with regard @@ -1184,6 +1243,11 @@ void RecordLayoutBuilder::Layout(const RecordDecl *D) { } void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { + if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) { + MSLayout(RD); + return ; + } + InitializeLayout(RD); // Lay out the vtable and the non-virtual bases. @@ -1193,7 +1257,7 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { NonVirtualSize = Context.toCharUnitsFromBits( llvm::RoundUpToAlignment(getSizeInBits(), - Context.Target.getCharAlign())); + Context.getTargetInfo().getCharAlign())); NonVirtualAlignment = Alignment; // Lay out the virtual bases and add the primary virtual base offsets. @@ -1242,10 +1306,9 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { } InitializeLayout(D); - ObjCInterfaceDecl *OI = const_cast<ObjCInterfaceDecl*>(D); // Layout each ivar sequentially. - for (ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) + for (const ObjCIvarDecl *IVD = D->all_declared_ivar_begin(); IVD; + IVD = IVD->getNextIvar()) LayoutField(IVD); // Finally, round the size of the total struct up to the alignment of the @@ -1271,8 +1334,8 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { continue; // FIXME. streamline these conditions into a simple one. else if (Context.BitfieldFollowsBitfield(FD, LastFD) || - Context.BitfieldFollowsNoneBitfield(FD, LastFD) || - Context.NoneBitfieldFollowsBitfield(FD, LastFD)) { + Context.BitfieldFollowsNonBitfield(FD, LastFD) || + Context.NonBitfieldFollowsBitfield(FD, LastFD)) { // 1) Adjacent bit fields are packed into the same 1-, 2-, or // 4-byte allocation unit if the integral types are the same // size and if the next bit field fits into the current @@ -1299,14 +1362,14 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { if (TypeSizeLastFD != TypeSize) { if (RemainingInAlignment && LastFD && LastFD->isBitField() && - LastFD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) { + LastFD->getBitWidthValue(Context)) { // If previous field was a bitfield with some remaining unfilled // bits, pad the field so current field starts on its type boundary. uint64_t FieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset; setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.Target.getCharAlign())); + Context.getTargetInfo().getCharAlign())); setSize(std::max(getSizeInBits(), getDataSizeInBits())); RemainingInAlignment = 0; } @@ -1325,13 +1388,12 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { uint64_t NewSizeInBits = llvm::RoundUpToAlignment(UnpaddedFieldOffset, FieldAlign); setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.Target.getCharAlign())); + Context.getTargetInfo().getCharAlign())); UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; setSize(std::max(getSizeInBits(), getDataSizeInBits())); } if (FD->isBitField()) { - uint64_t FieldSize = - FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + uint64_t FieldSize = FD->getBitWidthValue(Context); assert (FieldSize > 0 && "LayoutFields - ms_struct layout"); if (RemainingInAlignment < FieldSize) RemainingInAlignment = TypeSize - FieldSize; @@ -1340,8 +1402,7 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { } } else if (FD->isBitField()) { - uint64_t FieldSize = - FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + uint64_t FieldSize = FD->getBitWidthValue(Context); std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(FD->getType()); uint64_t TypeSize = FieldInfo.first; @@ -1349,18 +1410,23 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { } LastFD = FD; } + else if (!Context.getTargetInfo().useBitFieldTypeAlignment() && + Context.getTargetInfo().useZeroLengthBitfieldAlignment()) { + FieldDecl *FD = (*Field); + if (FD->isBitField() && FD->getBitWidthValue(Context) == 0) + ZeroLengthBitfield = FD; + } LayoutField(*Field); } if (IsMsStruct && RemainingInAlignment && - LastFD && LastFD->isBitField() && - LastFD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) { + LastFD && LastFD->isBitField() && LastFD->getBitWidthValue(Context)) { // If we ended a bitfield before the full length of the type then // pad the struct out to the full length of the last type. uint64_t FieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset; setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.Target.getCharAlign())); + Context.getTargetInfo().getCharAlign())); setSize(std::max(getSizeInBits(), getDataSizeInBits())); } } @@ -1405,15 +1471,15 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, setDataSize(std::max(getDataSizeInBits(), FieldSize)); FieldOffset = 0; } else { - // The bitfield is allocated starting at the next offset aligned appropriately - // for T', with length n bits. + // The bitfield is allocated starting at the next offset aligned + // appropriately for T', with length n bits. FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(), Context.toBits(TypeAlign)); uint64_t NewSizeInBits = FieldOffset + FieldSize; setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.Target.getCharAlign())); + Context.getTargetInfo().getCharAlign())); UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; } @@ -1434,7 +1500,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset; - uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + uint64_t FieldSize = D->getBitWidthValue(Context); std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType()); uint64_t TypeSize = FieldInfo.first; @@ -1443,21 +1509,32 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // This check is needed for 'long long' in -m32 mode. if (IsMsStruct && (TypeSize > FieldAlign)) FieldAlign = TypeSize; - + if (ZeroLengthBitfield) { - // If a zero-length bitfield is inserted after a bitfield, - // and the alignment of the zero-length bitfield is - // greater than the member that follows it, `bar', `bar' - // will be aligned as the type of the zero-length bitfield. - if (ZeroLengthBitfield != D) { - std::pair<uint64_t, unsigned> FieldInfo = - Context.getTypeInfo(ZeroLengthBitfield->getType()); - unsigned ZeroLengthBitfieldAlignment = FieldInfo.second; - // Ignore alignment of subsequent zero-length bitfields. - if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0)) - FieldAlign = ZeroLengthBitfieldAlignment; - if (FieldSize) - ZeroLengthBitfield = 0; + std::pair<uint64_t, unsigned> FieldInfo; + unsigned ZeroLengthBitfieldAlignment; + if (IsMsStruct) { + // If a zero-length bitfield is inserted after a bitfield, + // and the alignment of the zero-length bitfield is + // greater than the member that follows it, `bar', `bar' + // will be aligned as the type of the zero-length bitfield. + if (ZeroLengthBitfield != D) { + FieldInfo = Context.getTypeInfo(ZeroLengthBitfield->getType()); + ZeroLengthBitfieldAlignment = FieldInfo.second; + // Ignore alignment of subsequent zero-length bitfields. + if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0)) + FieldAlign = ZeroLengthBitfieldAlignment; + if (FieldSize) + ZeroLengthBitfield = 0; + } + } else { + // The alignment of a zero-length bitfield affects the alignment + // of the next member. The alignment is the max of the zero + // length bitfield's alignment and a target specific fixed value. + unsigned ZeroLengthBitfieldBoundary = + Context.getTargetInfo().getZeroLengthBitfieldBoundary(); + if (ZeroLengthBitfieldBoundary > FieldAlign) + FieldAlign = ZeroLengthBitfieldBoundary; } } @@ -1470,10 +1547,11 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // was unnecessary (-Wpacked). unsigned UnpackedFieldAlign = FieldAlign; uint64_t UnpackedFieldOffset = FieldOffset; - if (!Context.Target.useBitFieldTypeAlignment()) + if (!Context.getTargetInfo().useBitFieldTypeAlignment() && !ZeroLengthBitfield) UnpackedFieldAlign = 1; - if (FieldPacked || !Context.Target.useBitFieldTypeAlignment()) + if (FieldPacked || + (!Context.getTargetInfo().useBitFieldTypeAlignment() && !ZeroLengthBitfield)) FieldAlign = 1; FieldAlign = std::max(FieldAlign, D->getMaxAlignment()); UnpackedFieldAlign = std::max(UnpackedFieldAlign, D->getMaxAlignment()); @@ -1494,10 +1572,14 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, UnpackedFieldAlign); - // Padding members don't affect overall alignment. - if (!D->getIdentifier()) + // Padding members don't affect overall alignment, unless zero length bitfield + // alignment is enabled. + if (!D->getIdentifier() && !Context.getTargetInfo().useZeroLengthBitfieldAlignment()) FieldAlign = UnpackedFieldAlign = 1; + if (!IsMsStruct) + ZeroLengthBitfield = 0; + // Place this field at the current location. FieldOffsets.push_back(FieldOffset); @@ -1512,7 +1594,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { uint64_t NewSizeInBits = FieldOffset + FieldSize; setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.Target.getCharAlign())); + Context.getTargetInfo().getCharAlign())); UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; } @@ -1552,25 +1634,36 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) { unsigned AS = RT->getPointeeType().getAddressSpace(); FieldSize = - Context.toCharUnitsFromBits(Context.Target.getPointerWidth(AS)); + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS)); FieldAlign = - Context.toCharUnitsFromBits(Context.Target.getPointerAlign(AS)); + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(AS)); } else { std::pair<CharUnits, CharUnits> FieldInfo = Context.getTypeInfoInChars(D->getType()); FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; - + if (ZeroLengthBitfield) { - // If a zero-length bitfield is inserted after a bitfield, - // and the alignment of the zero-length bitfield is - // greater than the member that follows it, `bar', `bar' - // will be aligned as the type of the zero-length bitfield. - std::pair<CharUnits, CharUnits> FieldInfo = - Context.getTypeInfoInChars(ZeroLengthBitfield->getType()); - CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second; - if (ZeroLengthBitfieldAlignment > FieldAlign) - FieldAlign = ZeroLengthBitfieldAlignment; + CharUnits ZeroLengthBitfieldBoundary = + Context.toCharUnitsFromBits( + Context.getTargetInfo().getZeroLengthBitfieldBoundary()); + if (ZeroLengthBitfieldBoundary == CharUnits::Zero()) { + // If a zero-length bitfield is inserted after a bitfield, + // and the alignment of the zero-length bitfield is + // greater than the member that follows it, `bar', `bar' + // will be aligned as the type of the zero-length bitfield. + std::pair<CharUnits, CharUnits> FieldInfo = + Context.getTypeInfoInChars(ZeroLengthBitfield->getType()); + CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second; + if (ZeroLengthBitfieldAlignment > FieldAlign) + FieldAlign = ZeroLengthBitfieldAlignment; + } else if (ZeroLengthBitfieldBoundary > FieldAlign) { + // Align 'bar' based on a fixed alignment specified by the target. + assert(Context.getTargetInfo().useZeroLengthBitfieldAlignment() && + "ZeroLengthBitfieldBoundary should only be used in conjunction" + " with useZeroLengthBitfieldAlignment."); + FieldAlign = ZeroLengthBitfieldBoundary; + } ZeroLengthBitfield = 0; } @@ -1641,6 +1734,104 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { UpdateAlignment(FieldAlign, UnpackedFieldAlign); } +void RecordLayoutBuilder::MSLayoutVirtualBases(const CXXRecordDecl *RD) { + + if (!RD->getNumVBases()) + return; + + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), + E = RD->vbases_end(); I != E; ++I) { + + const CXXRecordDecl* BaseDecl = I->getType()->getAsCXXRecordDecl(); + const BaseSubobjectInfo* BaseInfo = VirtualBaseInfo.lookup(BaseDecl); + + assert(BaseInfo && "Did not find virtual base info!"); + + LayoutVirtualBase(BaseInfo); + } +} + +void RecordLayoutBuilder::MSLayout(const CXXRecordDecl *RD) { + + bool IsVBPtrAddedToLayout = false; + + InitializeLayout(RD); + + if (HasVBPtr(RD)) { + // If all bases are virtual and the class declares a new virtual function, + // MSVC builds a vfptr. + if (HasNewVirtualFunction(RD)) { + AddVPointer(); + } + + VBPtrOffset = getSize(); + AddVPointer(); + IsVBPtrAddedToLayout = true; + + ComputeBaseSubobjectInfo(RD); + } else { + LayoutNonVirtualBases(RD); + } + + if (RD->getNumVBases() && + !IsVBPtrAddedToLayout) { + // Add vbptr. + VBPtrOffset = getSize(); + AddVPointer(); + } + + LayoutFields(RD); + + NonVirtualSize = Context.toCharUnitsFromBits( + llvm::RoundUpToAlignment(getSizeInBits(), + Context.getTargetInfo().getCharAlign())); + NonVirtualAlignment = Alignment; + + if (NonVirtualSize != NonVirtualSize.RoundUpToAlignment(Alignment)) { + CharUnits AlignMember = + NonVirtualSize.RoundUpToAlignment(Alignment) - NonVirtualSize; + + setSize(getSize() + AlignMember); + setDataSize(getSize()); + + NonVirtualSize = Context.toCharUnitsFromBits( + llvm::RoundUpToAlignment(getSizeInBits(), + Context.getTargetInfo().getCharAlign())); + } + + MSLayoutVirtualBases(RD); + + VisitedVirtualBases.clear(); + + // Finally, round the size of the total struct up to the alignment of the + // struct itself. + if (!RD->getNumVBases()) + FinishLayout(RD); + +#ifndef NDEBUG + // Check that we have base offsets for all 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()); + + assert(Bases.count(BaseDecl) && "Did not find base offset!"); + } + + // And all virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), + E = RD->vbases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + assert(VBases.count(BaseDecl) && "Did not find base offset!"); + } +#endif +} + void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // In C++, records cannot be of size 0. if (Context.getLangOptions().CPlusPlus && getSizeInBits() == 0) { @@ -1663,7 +1854,7 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits); setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment))); - unsigned CharBitNum = Context.Target.getCharWidth(); + unsigned CharBitNum = Context.getTargetInfo().getCharWidth(); if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) { // Warn if padding was introduced to the struct/class/union. if (getSizeInBits() > UnpaddedSize) { @@ -1718,7 +1909,12 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, if (isa<ObjCIvarDecl>(D)) return; - unsigned CharBitNum = Context.Target.getCharWidth(); + // Don't warn about structs created without a SourceLocation. This can + // be done by clients of the AST, such as codegen. + if (D->getLocation().isInvalid()) + return; + + unsigned CharBitNum = Context.getTargetInfo().getCharWidth(); // Warn if padding was introduced to the struct/class. if (!IsUnion && Offset > UnpaddedOffset) { @@ -1802,36 +1998,18 @@ RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) { return Context.getDiagnostics().Report(Loc, DiagID); } -namespace { - // This class implements layout specific to the Microsoft ABI. - class MSRecordLayoutBuilder : public RecordLayoutBuilder { - public: - MSRecordLayoutBuilder(const ASTContext& Ctx, - EmptySubobjectMap *EmptySubobjects) : - RecordLayoutBuilder(Ctx, EmptySubobjects) {} - - virtual CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const; - }; -} - -CharUnits -MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const { - // We should reserve space for two pointers if the class has both - // virtual functions and virtual bases. - CharUnits PointerWidth = - Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); - if (RD->isPolymorphic() && RD->getNumVBases() > 0) - return 2 * PointerWidth; - return PointerWidth; -} - /// getASTRecordLayout - Get or compute information about the layout of the /// specified record (struct/union/class), which indicates its size and field /// position information. const ASTRecordLayout & ASTContext::getASTRecordLayout(const RecordDecl *D) const { + // These asserts test different things. A record has a definition + // as soon as we begin to parse the definition. That definition is + // not a complete definition (which is what isDefinition() tests) + // until we *finish* parsing the definition. D = D->getDefinition(); assert(D && "Cannot get layout of forward declarations!"); + assert(D->isCompleteDefinition() && "Cannot layout type before complete!"); // Look up this layout, if already laid out, return what we have. // Note that we can't save a reference to the entry because this function @@ -1844,25 +2022,44 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { EmptySubobjectMap EmptySubobjects(*this, RD); - // When compiling for Microsoft, use the special MS builder. llvm::OwningPtr<RecordLayoutBuilder> Builder; - switch (Target.getCXXABI()) { - default: - Builder.reset(new RecordLayoutBuilder(*this, &EmptySubobjects)); - break; - case CXXABI_Microsoft: - Builder.reset(new MSRecordLayoutBuilder(*this, &EmptySubobjects)); - } + CharUnits TargetAlign = CharUnits::One(); + + Builder.reset(new RecordLayoutBuilder(*this, + &EmptySubobjects, + TargetAlign)); + // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<RecordLayoutBuilder> RecordBuilderCleanup(Builder.get()); Builder->Layout(RD); + TargetAlign = Builder->getAligment(); + + if (getTargetInfo().getCXXABI() == CXXABI_Microsoft && + TargetAlign.getQuantity() > 4) { + // MSVC rounds the vtable pointer to the struct alignment in what must + // be a multi-pass operation. For now, let the builder figure out the + // alignment and recalculate the layout once its known. + Builder.reset(new RecordLayoutBuilder(*this, + &EmptySubobjects, + TargetAlign)); + + Builder->Layout(RD); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar<RecordLayoutBuilder> + RecordBuilderCleanup(Builder.get()); + } + // FIXME: This is not always correct. See the part about bitfields at // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info. // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout. - bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD(); + // This does not affect the calculations of MSVC layouts + bool IsPODForThePurposeOfLayout = + (getTargetInfo().getCXXABI() == CXXABI_Microsoft) || + cast<CXXRecordDecl>(D)->isPOD(); // FIXME: This should be done in FinalizeLayout. CharUnits DataSize = @@ -1873,6 +2070,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { NewEntry = new (*this) ASTRecordLayout(*this, Builder->getSize(), Builder->Alignment, + Builder->GetVBPtrOffset(), DataSize, Builder->FieldOffsets.data(), Builder->FieldOffsets.size(), @@ -1883,7 +2081,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { Builder->PrimaryBaseIsVirtual, Builder->Bases, Builder->VBases); } else { - RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); + RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0, CharUnits::One()); Builder.Layout(D); NewEntry = @@ -1915,8 +2113,8 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { return Entry; } -/// getInterfaceLayoutImpl - Get or compute information about the -/// layout of the given interface. +/// getObjCLayout - Get or compute information about the layout of the +/// given interface. /// /// \param Impl - If given, also include the layout of the interface's /// implementation. This may differ by including synthesized ivars. @@ -1942,7 +2140,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, return getObjCLayout(D, 0); } - RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); + RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0, CharUnits::One()); Builder.Layout(D); const ASTRecordLayout *NewEntry = @@ -1957,13 +2155,13 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, return *NewEntry; } -static void PrintOffset(llvm::raw_ostream &OS, +static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel) { OS << llvm::format("%4d | ", Offset.getQuantity()); OS.indent(IndentLevel * 2); } -static void DumpCXXRecordLayout(llvm::raw_ostream &OS, +static void DumpCXXRecordLayout(raw_ostream &OS, const CXXRecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, @@ -1982,12 +2180,22 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS, IndentLevel++; const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + bool HasVbptr = Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1); // Vtable pointer. if (RD->isDynamicClass() && !PrimaryBase) { PrintOffset(OS, Offset, IndentLevel); - OS << '(' << RD << " vtable pointer)\n"; + OS << '(' << *RD << " vtable pointer)\n"; + } + + if (HasVbptr && !PrimaryBase) { + PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); + OS << '(' << *RD << " vbtable pointer)\n"; + + // one vbtable per class + HasVbptr = false; } + // Dump (non-virtual) bases for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { @@ -2005,6 +2213,11 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS, Base == PrimaryBase ? "(primary base)" : "(base)", /*IncludeVirtualBases=*/false); } + // vbptr + if (HasVbptr) { + PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); + OS << '(' << *RD << " vbtable pointer)\n"; + } // Dump fields. uint64_t FieldNo = 0; @@ -2024,7 +2237,7 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS, } PrintOffset(OS, FieldOffset, IndentLevel); - OS << Field->getType().getAsString() << ' ' << Field << '\n'; + OS << Field->getType().getAsString() << ' ' << *Field << '\n'; } if (!IncludeVirtualBases) @@ -2053,7 +2266,7 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS, } void ASTContext::DumpRecordLayout(const RecordDecl *RD, - llvm::raw_ostream &OS) const { + raw_ostream &OS) const { const ASTRecordLayout &Info = getASTRecordLayout(RD); if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) diff --git a/contrib/llvm/tools/clang/lib/AST/SelectorLocationsKind.cpp b/contrib/llvm/tools/clang/lib/AST/SelectorLocationsKind.cpp new file mode 100644 index 0000000..671207a --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/SelectorLocationsKind.cpp @@ -0,0 +1,128 @@ +//===--- SelectorLocationsKind.cpp - Kind of selector locations -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Describes whether the identifier locations for a selector are "standard" +// or not. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/SelectorLocationsKind.h" +#include "clang/AST/Expr.h" + +using namespace clang; + +static SourceLocation getStandardSelLoc(unsigned Index, + Selector Sel, + bool WithArgSpace, + SourceLocation ArgLoc, + SourceLocation EndLoc) { + unsigned NumSelArgs = Sel.getNumArgs(); + if (NumSelArgs == 0) { + assert(Index == 0); + if (EndLoc.isInvalid()) + return SourceLocation(); + IdentifierInfo *II = Sel.getIdentifierInfoForSlot(0); + unsigned Len = II ? II->getLength() : 0; + return EndLoc.getLocWithOffset(-Len); + } + + assert(Index < NumSelArgs); + if (ArgLoc.isInvalid()) + return SourceLocation(); + IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Index); + unsigned Len = /* selector id */ (II ? II->getLength() : 0) + /* ':' */ 1; + if (WithArgSpace) + ++Len; + return ArgLoc.getLocWithOffset(-Len); +} + +namespace { + +template <typename T> +SourceLocation getArgLoc(T* Arg); + +template <> +SourceLocation getArgLoc<Expr>(Expr *Arg) { + return Arg->getLocStart(); +} + +template <> +SourceLocation getArgLoc<ParmVarDecl>(ParmVarDecl *Arg) { + SourceLocation Loc = Arg->getLocStart(); + if (Loc.isInvalid()) + return Loc; + // -1 to point to left paren of the method parameter's type. + return Loc.getLocWithOffset(-1); +} + +template <typename T> +SourceLocation getArgLoc(unsigned Index, ArrayRef<T*> Args) { + return Index < Args.size() ? getArgLoc(Args[Index]) : SourceLocation(); +} + +template <typename T> +SelectorLocationsKind hasStandardSelLocs(Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ArrayRef<T *> Args, + SourceLocation EndLoc) { + // Are selector locations in standard position with no space between args ? + unsigned i; + for (i = 0; i != SelLocs.size(); ++i) { + if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/false, + Args, EndLoc)) + break; + } + if (i == SelLocs.size()) + return SelLoc_StandardNoSpace; + + // Are selector locations in standard position with space between args ? + for (i = 0; i != SelLocs.size(); ++i) { + if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/true, + Args, EndLoc)) + return SelLoc_NonStandard; + } + + return SelLoc_StandardWithSpace; +} + +} // anonymous namespace + +SelectorLocationsKind +clang::hasStandardSelectorLocs(Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ArrayRef<Expr *> Args, + SourceLocation EndLoc) { + return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc); +} + +SourceLocation clang::getStandardSelectorLoc(unsigned Index, + Selector Sel, + bool WithArgSpace, + ArrayRef<Expr *> Args, + SourceLocation EndLoc) { + return getStandardSelLoc(Index, Sel, WithArgSpace, + getArgLoc(Index, Args), EndLoc); +} + +SelectorLocationsKind +clang::hasStandardSelectorLocs(Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ArrayRef<ParmVarDecl *> Args, + SourceLocation EndLoc) { + return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc); +} + +SourceLocation clang::getStandardSelectorLoc(unsigned Index, + Selector Sel, + bool WithArgSpace, + ArrayRef<ParmVarDecl *> Args, + SourceLocation EndLoc) { + return getStandardSelLoc(Index, Sel, WithArgSpace, + getArgLoc(Index, Args), EndLoc); +} diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index fd6f21d..e7b87e4 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -97,6 +97,22 @@ Stmt *Stmt::IgnoreImplicit() { return s; } +/// \brief Strip off all label-like statements. +/// +/// This will strip off label statements, case statements, and default +/// statements recursively. +const Stmt *Stmt::stripLabelLikeStatements() const { + const Stmt *S = this; + while (true) { + if (const LabelStmt *LS = dyn_cast<LabelStmt>(S)) + S = LS->getSubStmt(); + else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S)) + S = SC->getSubStmt(); + else + return S; + } +} + namespace { struct good {}; struct bad {}; @@ -214,7 +230,7 @@ Expr *AsmStmt::getOutputExpr(unsigned i) { /// getOutputConstraint - Return the constraint string for the specified /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). -llvm::StringRef AsmStmt::getOutputConstraint(unsigned i) const { +StringRef AsmStmt::getOutputConstraint(unsigned i) const { return getOutputConstraintLiteral(i)->getString(); } @@ -238,7 +254,7 @@ void AsmStmt::setInputExpr(unsigned i, Expr *E) { /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. -llvm::StringRef AsmStmt::getInputConstraint(unsigned i) const { +StringRef AsmStmt::getInputConstraint(unsigned i) const { return getInputConstraintLiteral(i)->getString(); } @@ -277,7 +293,7 @@ void AsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C, /// getNamedOperand - Given a symbolic operand reference like %[foo], /// translate this into a numeric value needed to reference the same operand. /// This returns -1 if the operand name is invalid. -int AsmStmt::getNamedOperand(llvm::StringRef SymbolicName) const { +int AsmStmt::getNamedOperand(StringRef SymbolicName) const { unsigned NumPlusOperands = 0; // Check if this is an output operand. @@ -297,9 +313,9 @@ int AsmStmt::getNamedOperand(llvm::StringRef SymbolicName) const { /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing /// it into pieces. If the asm string is erroneous, emit errors and return /// true, otherwise return false. -unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces, +unsigned AsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, ASTContext &C, unsigned &DiagOffs) const { - llvm::StringRef Str = getAsmString()->getString(); + StringRef Str = getAsmString()->getString(); const char *StrStart = Str.begin(); const char *StrEnd = Str.end(); const char *CurPtr = StrStart; @@ -326,7 +342,7 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces, // asm string. std::string CurStringPiece; - bool HasVariants = !C.Target.hasNoAsmVariants(); + bool HasVariants = !C.getTargetInfo().hasNoAsmVariants(); while (1) { // Done with the string? @@ -416,7 +432,7 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces, if (NameEnd == CurPtr) return diag::err_asm_empty_symbolic_operand_name; - llvm::StringRef SymbolicName(CurPtr, NameEnd - CurPtr); + StringRef SymbolicName(CurPtr, NameEnd - CurPtr); int N = getNamedOperand(SymbolicName); if (N == -1) { diff --git a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp index fb024f3..2968739 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp @@ -27,7 +27,7 @@ using namespace clang; namespace { class StmtDumper : public StmtVisitor<StmtDumper> { SourceManager *SM; - llvm::raw_ostream &OS; + raw_ostream &OS; unsigned IndentLevel; /// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump @@ -41,7 +41,7 @@ namespace { unsigned LastLocLine; public: - StmtDumper(SourceManager *sm, llvm::raw_ostream &os, unsigned maxDepth) + StmtDumper(SourceManager *sm, raw_ostream &os, unsigned maxDepth) : SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) { LastLocFilename = ""; LastLocLine = ~0U; @@ -235,9 +235,9 @@ void StmtDumper::DumpDeclarator(Decl *D) { // nodes are where they need to be. if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) { OS << "\"typedef " << localType->getUnderlyingType().getAsString() - << ' ' << localType << '"'; + << ' ' << *localType << '"'; } else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) { - OS << "\"using " << localType << " = " + OS << "\"using " << *localType << " = " << localType->getUnderlyingType().getAsString() << '"'; } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { OS << "\""; @@ -294,7 +294,7 @@ void StmtDumper::DumpDeclarator(Decl *D) { DumpSubTree(SAD->getMessage()); OS << ");\""; } else { - assert(0 && "Unexpected decl"); + llvm_unreachable("Unexpected decl"); } } @@ -333,7 +333,7 @@ void StmtDumper::VisitExpr(Expr *Node) { DumpExpr(Node); } -static void DumpBasePath(llvm::raw_ostream &OS, CastExpr *Node) { +static void DumpBasePath(raw_ostream &OS, CastExpr *Node) { if (Node->path_empty()) return; @@ -407,7 +407,7 @@ void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { DumpExpr(Node); OS << " " << Node->getDecl()->getDeclKindName() - << "Decl='" << Node->getDecl() + << "Decl='" << *Node->getDecl() << "' " << (void*)Node->getDecl(); if (Node->isFreeIvar()) OS << " isFreeIvar"; @@ -416,7 +416,7 @@ void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) { DumpExpr(Node); switch (Node->getIdentType()) { - default: assert(0 && "unknown case"); + default: llvm_unreachable("unknown case"); case PredefinedExpr::Func: OS << " __func__"; break; case PredefinedExpr::Function: OS << " __FUNCTION__"; break; case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; @@ -443,8 +443,13 @@ void StmtDumper::VisitStringLiteral(StringLiteral *Str) { DumpExpr(Str); // FIXME: this doesn't print wstrings right. OS << " "; - if (Str->isWide()) - OS << "L"; + switch (Str->getKind()) { + case StringLiteral::Ascii: break; // No prefix + case StringLiteral::Wide: OS << 'L'; break; + case StringLiteral::UTF8: OS << "u8"; break; + case StringLiteral::UTF16: OS << 'u'; break; + case StringLiteral::UTF32: OS << 'U'; break; + } OS << '"'; OS.write_escaped(Str->getString()); OS << '"'; @@ -475,7 +480,7 @@ void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { void StmtDumper::VisitMemberExpr(MemberExpr *Node) { DumpExpr(Node); OS << " " << (Node->isArrow() ? "->" : ".") - << Node->getMemberDecl() << ' ' + << *Node->getMemberDecl() << ' ' << (void*)Node->getMemberDecl(); } void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { @@ -552,7 +557,8 @@ void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) { void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { DumpExpr(Node); - OS << " functional cast to " << Node->getTypeAsWritten().getAsString(); + OS << " functional cast to " << Node->getTypeAsWritten().getAsString() + << " <" << Node->getCastKindName() << ">"; } void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) { @@ -637,7 +643,7 @@ void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { DumpExpr(Node); - OS << ' ' << Node->getProtocol(); + OS << ' ' <<* Node->getProtocol(); } void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { @@ -656,7 +662,7 @@ void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { OS << "(null)"; OS << "\""; } else { - OS << " Kind=PropertyRef Property=\"" << Node->getExplicitProperty() << '"'; + OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"'; } if (Node->isSuperReceiver()) @@ -674,7 +680,7 @@ void Stmt::dump(SourceManager &SM) const { dump(llvm::errs(), SM); } -void Stmt::dump(llvm::raw_ostream &OS, SourceManager &SM) const { +void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { StmtDumper P(&SM, OS, 4); P.DumpSubTree(const_cast<Stmt*>(this)); OS << "\n"; diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index f705a84..daaa354 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -28,14 +28,14 @@ using namespace clang; namespace { class StmtPrinter : public StmtVisitor<StmtPrinter> { - llvm::raw_ostream &OS; + raw_ostream &OS; ASTContext &Context; unsigned IndentLevel; clang::PrinterHelper* Helper; PrintingPolicy Policy; public: - StmtPrinter(llvm::raw_ostream &os, ASTContext &C, PrinterHelper* helper, + StmtPrinter(raw_ostream &os, ASTContext &C, PrinterHelper* helper, const PrintingPolicy &Policy, unsigned Indentation = 0) : OS(os), Context(C), IndentLevel(Indentation), Helper(helper), @@ -76,7 +76,7 @@ namespace { OS << "<null expr>"; } - llvm::raw_ostream &Indent(int Delta = 0) { + raw_ostream &Indent(int Delta = 0) { for (int i = 0, e = IndentLevel+Delta; i < e; ++i) OS << " "; return OS; @@ -124,7 +124,7 @@ void StmtPrinter::PrintRawDecl(Decl *D) { void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) { DeclStmt::decl_iterator Begin = S->decl_begin(), End = S->decl_end(); - llvm::SmallVector<Decl*, 2> Decls; + SmallVector<Decl*, 2> Decls; for ( ; Begin != End; ++Begin) Decls.push_back(*Begin); @@ -564,7 +564,7 @@ void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { PrintExpr(Node->getBase()); OS << (Node->isArrow() ? "->" : "."); } - OS << Node->getDecl(); + OS << *Node->getDecl(); } void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { @@ -584,7 +584,7 @@ void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) { switch (Node->getIdentType()) { default: - assert(0 && "unknown case"); + llvm_unreachable("unknown case"); case PredefinedExpr::Func: OS << "__func__"; break; @@ -599,8 +599,14 @@ void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) { void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { unsigned value = Node->getValue(); - if (Node->isWide()) - OS << "L"; + + switch (Node->getKind()) { + case CharacterLiteral::Ascii: break; // no prefix. + case CharacterLiteral::Wide: OS << 'L'; break; + case CharacterLiteral::UTF16: OS << 'u'; break; + case CharacterLiteral::UTF32: OS << 'U'; break; + } + switch (value) { case '\\': OS << "'\\\\'"; @@ -652,7 +658,7 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { // Emit suffixes. Integer literals are always a builtin integer type. switch (Node->getType()->getAs<BuiltinType>()->getKind()) { - default: assert(0 && "Unexpected type for integer literal!"); + default: llvm_unreachable("Unexpected type for integer literal!"); case BuiltinType::Int: break; // no suffix. case BuiltinType::UInt: OS << 'U'; break; case BuiltinType::Long: OS << 'L'; break; @@ -662,8 +668,9 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { } } void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) { - // FIXME: print value more precisely. - OS << Node->getValueAsApproximateDouble(); + llvm::SmallString<16> Str; + Node->getValue().toString(Str); + OS << Str; } void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) { @@ -672,12 +679,18 @@ void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) { } void StmtPrinter::VisitStringLiteral(StringLiteral *Str) { - if (Str->isWide()) OS << 'L'; + switch (Str->getKind()) { + case StringLiteral::Ascii: break; // no prefix. + case StringLiteral::Wide: OS << 'L'; break; + case StringLiteral::UTF8: OS << "u8"; break; + case StringLiteral::UTF16: OS << 'u'; break; + case StringLiteral::UTF32: OS << 'U'; break; + } OS << '"'; // FIXME: this doesn't print wstrings right. - llvm::StringRef StrData = Str->getString(); - for (llvm::StringRef::iterator I = StrData.begin(), E = StrData.end(); + StringRef StrData = Str->getString(); + for (StringRef::iterator I = StrData.begin(), E = StrData.end(); I != E; ++I) { unsigned char Char = *I; @@ -998,6 +1011,59 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { OS << ")"; } +void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { + const char *Name = 0; + switch (Node->getOp()) { + case AtomicExpr::Load: + Name = "__atomic_load("; + break; + case AtomicExpr::Store: + Name = "__atomic_store("; + break; + case AtomicExpr::CmpXchgStrong: + Name = "__atomic_compare_exchange_strong("; + break; + case AtomicExpr::CmpXchgWeak: + Name = "__atomic_compare_exchange_weak("; + break; + case AtomicExpr::Xchg: + Name = "__atomic_exchange("; + break; + case AtomicExpr::Add: + Name = "__atomic_fetch_add("; + break; + case AtomicExpr::Sub: + Name = "__atomic_fetch_sub("; + break; + case AtomicExpr::And: + Name = "__atomic_fetch_and("; + break; + case AtomicExpr::Or: + Name = "__atomic_fetch_or("; + break; + case AtomicExpr::Xor: + Name = "__atomic_fetch_xor("; + break; + } + OS << Name; + PrintExpr(Node->getPtr()); + OS << ", "; + if (Node->getOp() != AtomicExpr::Load) { + PrintExpr(Node->getVal1()); + OS << ", "; + } + if (Node->isCmpXChg()) { + PrintExpr(Node->getVal2()); + OS << ", "; + } + PrintExpr(Node->getOrder()); + if (Node->isCmpXChg()) { + OS << ", "; + PrintExpr(Node->getOrderFail()); + } + OS << ")"; +} + // C++ void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) { const char *OpStrings[NUM_OVERLOADED_OPERATORS] = { @@ -1039,7 +1105,7 @@ void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) { OS << ' ' << OpStrings[Kind] << ' '; PrintExpr(Node->getArg(1)); } else { - assert(false && "unknown overloaded operator"); + llvm_unreachable("unknown overloaded operator"); } } @@ -1438,7 +1504,7 @@ void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { } void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { - OS << "@protocol(" << Node->getProtocol() << ')'; + OS << "@protocol(" << *Node->getProtocol() << ')'; } void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) { @@ -1520,7 +1586,7 @@ void StmtPrinter::VisitBlockExpr(BlockExpr *Node) { } void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) { - OS << Node->getDecl(); + OS << *Node->getDecl(); } void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {} @@ -1541,7 +1607,7 @@ void Stmt::dumpPretty(ASTContext& Context) const { PrintingPolicy(Context.getLangOptions())); } -void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context, +void Stmt::printPretty(raw_ostream &OS, ASTContext& Context, PrinterHelper* Helper, const PrintingPolicy &Policy, unsigned Indentation) const { diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index 120c9e5..214378a 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -252,7 +252,7 @@ void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) { void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) { VisitExpr(S); - ID.AddBoolean(S->isWide()); + ID.AddInteger(S->getKind()); ID.AddInteger(S->getValue()); } @@ -269,7 +269,7 @@ void StmtProfiler::VisitImaginaryLiteral(const ImaginaryLiteral *S) { void StmtProfiler::VisitStringLiteral(const StringLiteral *S) { VisitExpr(S); ID.AddString(S->getString()); - ID.AddBoolean(S->isWide()); + ID.AddInteger(S->getKind()); } void StmtProfiler::VisitParenExpr(const ParenExpr *S) { @@ -468,6 +468,11 @@ void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { } } +void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) { + VisitExpr(S); + ID.AddInteger(S->getOp()); +} + static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, UnaryOperatorKind &UnaryOp, BinaryOperatorKind &BinaryOp) { diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index 56c6e7b..0c011a8 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -33,7 +33,7 @@ using namespace clang; /// /// \param Out the raw_ostream instance to use for printing. static void printIntegral(const TemplateArgument &TemplArg, - llvm::raw_ostream &Out) { + raw_ostream &Out) { const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); const llvm::APSInt *Val = TemplArg.getAsIntegral(); @@ -68,8 +68,7 @@ TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, bool TemplateArgument::isDependent() const { switch (getKind()) { case Null: - assert(false && "Should not have a NULL template argument"); - return false; + llvm_unreachable("Should not have a NULL template argument"); case Type: return getAsType()->isDependentType(); @@ -107,8 +106,7 @@ bool TemplateArgument::isDependent() const { bool TemplateArgument::isInstantiationDependent() const { switch (getKind()) { case Null: - assert(false && "Should not have a NULL template argument"); - return false; + llvm_unreachable("Should not have a NULL template argument"); case Type: return getAsType()->isInstantiationDependentType(); @@ -309,7 +307,7 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const { } void TemplateArgument::print(const PrintingPolicy &Policy, - llvm::raw_ostream &Out) const { + raw_ostream &Out) const { switch (getKind()) { case Null: Out << "<no value>"; @@ -530,3 +528,65 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, return DB; } + +const ASTTemplateArgumentListInfo * +ASTTemplateArgumentListInfo::Create(ASTContext &C, + const TemplateArgumentListInfo &List) { + std::size_t size = sizeof(CXXDependentScopeMemberExpr) + + ASTTemplateArgumentListInfo::sizeFor(List); + void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); + ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo(); + TAI->initializeFrom(List); + return TAI; +} + +void ASTTemplateArgumentListInfo::initializeFrom( + const TemplateArgumentListInfo &Info) { + LAngleLoc = Info.getLAngleLoc(); + RAngleLoc = Info.getRAngleLoc(); + NumTemplateArgs = Info.size(); + + TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) + new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); +} + +void ASTTemplateArgumentListInfo::initializeFrom( + const TemplateArgumentListInfo &Info, + bool &Dependent, + bool &InstantiationDependent, + bool &ContainsUnexpandedParameterPack) { + LAngleLoc = Info.getLAngleLoc(); + RAngleLoc = Info.getRAngleLoc(); + NumTemplateArgs = Info.size(); + + TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) { + Dependent = Dependent || Info[i].getArgument().isDependent(); + InstantiationDependent = InstantiationDependent || + Info[i].getArgument().isInstantiationDependent(); + ContainsUnexpandedParameterPack + = ContainsUnexpandedParameterPack || + Info[i].getArgument().containsUnexpandedParameterPack(); + + new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); + } +} + +void ASTTemplateArgumentListInfo::copyInto( + TemplateArgumentListInfo &Info) const { + Info.setLAngleLoc(LAngleLoc); + Info.setRAngleLoc(RAngleLoc); + for (unsigned I = 0; I != NumTemplateArgs; ++I) + Info.addArgument(getTemplateArgs()[I]); +} + +std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) { + return sizeof(ASTTemplateArgumentListInfo) + + sizeof(TemplateArgumentLoc) * NumTemplateArgs; +} + +std::size_t ASTTemplateArgumentListInfo::sizeFor( + const TemplateArgumentListInfo &Info) { + return sizeFor(Info.size()); +} diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp index 1f7b19a..a0487ba 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp @@ -125,16 +125,16 @@ bool TemplateName::containsUnexpandedParameterPack() const { } void -TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy, +TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, bool SuppressNNS) const { if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) - OS << Template; + OS << *Template; else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { if (!SuppressNNS) QTN->getQualifier()->print(OS, Policy); if (QTN->hasTemplateKeyword()) OS << "template "; - OS << QTN->getDecl(); + OS << *QTN->getDecl(); } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { if (!SuppressNNS && DTN->getQualifier()) DTN->getQualifier()->print(OS, Policy); diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 08971eb..44eeec0 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -42,6 +42,26 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { (hasObjCLifetime() && !Other.hasObjCLifetime())); } +const IdentifierInfo* QualType::getBaseTypeIdentifier() const { + const Type* ty = getTypePtr(); + NamedDecl *ND = NULL; + if (ty->isPointerType() || ty->isReferenceType()) + return ty->getPointeeType().getBaseTypeIdentifier(); + else if (ty->isRecordType()) + ND = ty->getAs<RecordType>()->getDecl(); + else if (ty->isEnumeralType()) + ND = ty->getAs<EnumType>()->getDecl(); + else if (ty->getTypeClass() == Type::Typedef) + ND = ty->getAs<TypedefType>()->getDecl(); + else if (ty->isArrayType()) + return ty->castAsArrayTypeUnsafe()-> + getElementType().getBaseTypeIdentifier(); + + if (ND) + return ND->getIdentifier(); + return NULL; +} + bool QualType::isConstant(QualType T, ASTContext &Ctx) { if (T.isConstQualified()) return true; @@ -635,6 +655,18 @@ bool Type::isWideCharType() const { return false; } +bool Type::isChar16Type() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Char16; + return false; +} + +bool Type::isChar32Type() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Char32; + return false; +} + /// \brief Determine whether this type is any of the built-in character /// types. bool Type::isAnyCharacterType() const { @@ -734,9 +766,16 @@ bool Type::hasUnsignedIntegerRepresentation() const { return isUnsignedIntegerType(); } +bool Type::isHalfType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Half; + // FIXME: Should we allow complex __fp16? Probably not. + return false; +} + bool Type::isFloatingType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() >= BuiltinType::Float && + return BT->getKind() >= BuiltinType::Half && BT->getKind() <= BuiltinType::LongDouble; if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType)) return CT->getElementType()->isFloatingType(); @@ -801,14 +840,16 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { const Type *T = CanonicalType.getTypePtr(); if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) { if (BT->getKind() == BuiltinType::Bool) return STK_Bool; - if (BT->getKind() == BuiltinType::NullPtr) return STK_Pointer; + if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer; if (BT->isInteger()) return STK_Integral; if (BT->isFloatingPoint()) return STK_Floating; llvm_unreachable("unknown scalar builtin type"); - } else if (isa<PointerType>(T) || - isa<BlockPointerType>(T) || - isa<ObjCObjectPointerType>(T)) { - return STK_Pointer; + } else if (isa<PointerType>(T)) { + return STK_CPointer; + } else if (isa<BlockPointerType>(T)) { + return STK_BlockPointer; + } else if (isa<ObjCObjectPointerType>(T)) { + return STK_ObjCObjectPointer; } else if (isa<MemberPointerType>(T)) { return STK_MemberPointer; } else if (isa<EnumType>(T)) { @@ -821,7 +862,6 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { } llvm_unreachable("unknown scalar type"); - return STK_Pointer; } /// \brief Determines whether the type is a C++ aggregate type or C @@ -872,7 +912,7 @@ bool Type::isIncompleteType() const { case Record: // A tagged type (struct/union/enum/class) is incomplete if the decl is a // forward declaration, but not a full definition (C99 6.2.5p22). - return !cast<TagType>(CanonicalType)->getDecl()->isDefinition(); + return !cast<TagType>(CanonicalType)->getDecl()->isCompleteDefinition(); case ConstantArray: // An array is incomplete if its element type is incomplete // (C++ [dcl.array]p1). @@ -1073,7 +1113,7 @@ bool Type::isLiteralType() const { // C++0x [basic.types]p10: // A type is a literal type if it is: // [...] - // -- an array of literal type + // -- an array of literal type. // Extension: variable arrays cannot be literal types, since they're // runtime-sized. if (isVariableArrayType()) @@ -1093,33 +1133,31 @@ bool Type::isLiteralType() const { // C++0x [basic.types]p10: // A type is a literal type if it is: // -- a scalar type; or - // As an extension, Clang treats vector types as Scalar types. - if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; + // As an extension, Clang treats vector types as literal types. + if (BaseTy->isScalarType() || BaseTy->isVectorType()) + return true; // -- a reference type; or - if (BaseTy->isReferenceType()) return true; + if (BaseTy->isReferenceType()) + return true; // -- a class type that has all of the following properties: if (const RecordType *RT = BaseTy->getAs<RecordType>()) { + // -- a trivial destructor, + // -- every constructor call and full-expression in the + // brace-or-equal-initializers for non-static data members (if any) + // is a constant expression, + // -- it is an aggregate type or has at least one constexpr + // constructor or constructor template that is not a copy or move + // constructor, and + // -- all non-static data members and base classes of literal types + // + // We resolve DR1361 by ignoring the second bullet. if (const CXXRecordDecl *ClassDecl = - dyn_cast<CXXRecordDecl>(RT->getDecl())) { - // -- a trivial destructor, - if (!ClassDecl->hasTrivialDestructor()) return false; - // -- every constructor call and full-expression in the - // brace-or-equal-initializers for non-static data members (if any) - // is a constant expression, - // FIXME: C++0x: Clang doesn't yet support non-static data member - // declarations with initializers, or constexprs. - // -- it is an aggregate type or has at least one constexpr - // constructor or constructor template that is not a copy or move - // constructor, and - if (!ClassDecl->isAggregate() && - !ClassDecl->hasConstExprNonCopyMoveConstructor()) - return false; - // -- all non-static data members and base classes of literal types - if (ClassDecl->hasNonLiteralTypeFieldsOrBases()) return false; - } + dyn_cast<CXXRecordDecl>(RT->getDecl())) + return ClassDecl->isLiteral(); return true; } + return false; } @@ -1158,7 +1196,7 @@ bool Type::isStandardLayoutType() const { } // This is effectively the intersection of isTrivialType and -// isStandardLayoutType. We implement it dircetly to avoid redundant +// isStandardLayoutType. We implement it directly to avoid redundant // conversions from a type to a CXXRecordDecl. bool QualType::isCXX11PODType(ASTContext &Context) const { const Type *ty = getTypePtr(); @@ -1426,10 +1464,10 @@ const char *Type::getTypeClassName() const { return 0; } -const char *BuiltinType::getName(const LangOptions &LO) const { +const char *BuiltinType::getName(const PrintingPolicy &Policy) const { switch (getKind()) { case Void: return "void"; - case Bool: return LO.Bool ? "bool" : "_Bool"; + case Bool: return Policy.Bool ? "bool" : "_Bool"; case Char_S: return "char"; case Char_U: return "char"; case SChar: return "signed char"; @@ -1444,6 +1482,7 @@ const char *BuiltinType::getName(const LangOptions &LO) const { case ULong: return "unsigned long"; case ULongLong: return "unsigned long long"; case UInt128: return "__uint128_t"; + case Half: return "half"; case Float: return "float"; case Double: return "double"; case LongDouble: return "long double"; @@ -1481,7 +1520,7 @@ QualType QualType::getNonLValueExprType(ASTContext &Context) const { return *this; } -llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) { +StringRef FunctionType::getNameForCallConv(CallingConv CC) { switch (CC) { case CC_Default: llvm_unreachable("no name for default cc"); @@ -1716,7 +1755,7 @@ static TagDecl *getInterestingTagDecl(TagDecl *decl) { for (TagDecl::redecl_iterator I = decl->redecls_begin(), E = decl->redecls_end(); I != E; ++I) { - if (I->isDefinition() || I->isBeingDefined()) + if (I->isCompleteDefinition() || I->isBeingDefined()) return *I; } // If there's no definition (not even in progress), return what we have. @@ -2082,6 +2121,8 @@ static CachedProperties computeCachedProperties(const Type *T) { return Cache::get(cast<ObjCObjectType>(T)->getBaseType()); case Type::ObjCObjectPointer: return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType()); + case Type::Atomic: + return Cache::get(cast<AtomicType>(T)->getValueType()); } llvm_unreachable("unhandled type class"); @@ -2227,13 +2268,13 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { /// with non-trivial destructors. const CXXRecordDecl *record = type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); - if (record && !record->hasTrivialDestructor()) + if (record && record->hasDefinition() && !record->hasTrivialDestructor()) return DK_cxx_destructor; return DK_none; } -bool QualType::hasTrivialCopyAssignment(ASTContext &Context) const { +bool QualType::hasTrivialAssignment(ASTContext &Context, bool Copying) const { switch (getObjCLifetime()) { case Qualifiers::OCL_None: break; @@ -2249,7 +2290,8 @@ bool QualType::hasTrivialCopyAssignment(ASTContext &Context) const { if (const CXXRecordDecl *Record = getTypePtr()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) - return Record->hasTrivialCopyAssignment(); + return Copying ? Record->hasTrivialCopyAssignment() : + Record->hasTrivialMoveAssignment(); return true; } diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 34e7693..8e8b227 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -206,7 +206,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::Char_S: return TST_char; case BuiltinType::Char16: - return TST_char16; + return TST_char16; case BuiltinType::Char32: return TST_char32; case BuiltinType::WChar_S: @@ -225,6 +225,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::Long: case BuiltinType::LongLong: case BuiltinType::Int128: + case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index b89d2aa..fb7b918 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -123,6 +123,7 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { case Type::DependentTemplateSpecialization: case Type::ObjCObject: case Type::ObjCInterface: + case Type::Atomic: CanPrefixQualifiers = true; break; @@ -205,11 +206,11 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) { if (S.empty()) { - S = T->getName(Policy.LangOpts); + S = T->getName(Policy); } else { // Prefix the basic type, e.g. 'int X'. S = ' ' + S; - S = T->getName(Policy.LangOpts) + S; + S = T->getName(Policy) + S; } } @@ -581,6 +582,16 @@ void TypePrinter::printAuto(const AutoType *T, std::string &S) { } } +void TypePrinter::printAtomic(const AtomicType *T, std::string &S) { + if (!S.empty()) + S = ' ' + S; + std::string Str; + IncludeStrongLifetimeRAII Strong(Policy); + print(T->getValueType(), Str); + + S = "_Atomic(" + Str + ")" + S; +} + /// Appends the given scope to the end of a string. void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { if (DC->isTranslationUnit()) return; diff --git a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp new file mode 100644 index 0000000..f5ff624 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp @@ -0,0 +1,212 @@ +//===--- VTTBuilder.cpp - C++ VTT layout builder --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code dealing with generation of the layout of virtual table +// tables (VTT). +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/VTTBuilder.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/RecordLayout.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/Support/Format.h" +#include <algorithm> +#include <cstdio> + +using namespace clang; + +#define DUMP_OVERRIDERS 0 + +VTTBuilder::VTTBuilder(ASTContext &Ctx, + const CXXRecordDecl *MostDerivedClass, + bool GenerateDefinition) + : Ctx(Ctx), MostDerivedClass(MostDerivedClass), + MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)), + GenerateDefinition(GenerateDefinition) { + // Lay out this VTT. + LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()), + /*BaseIsVirtual=*/false); +} + +void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, + const CXXRecordDecl *VTableClass) { + // Store the vtable pointer index if we're generating the primary VTT. + if (VTableClass == MostDerivedClass) { + assert(!SecondaryVirtualPointerIndices.count(Base) && + "A virtual pointer index already exists for this base subobject!"); + SecondaryVirtualPointerIndices[Base] = VTTComponents.size(); + } + + if (!GenerateDefinition) { + VTTComponents.push_back(VTTComponent()); + return; + } + + VTTComponents.push_back(VTTComponent(VTableIndex, Base)); +} + +void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { + const CXXRecordDecl *RD = Base.getBase(); + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + + // Don't layout virtual bases. + if (I->isVirtual()) + continue; + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + CharUnits BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); + + // Layout the VTT for this base. + LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false); + } +} + +void +VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, + bool BaseIsMorallyVirtual, + uint64_t VTableIndex, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy &VBases) { + const CXXRecordDecl *RD = Base.getBase(); + + // We're not interested in bases that don't have virtual bases, and not + // morally virtual bases. + if (!RD->getNumVBases() && !BaseIsMorallyVirtual) + return; + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Itanium C++ ABI 2.6.2: + // Secondary virtual pointers are present for all bases with either + // virtual bases or virtual function declarations overridden along a + // virtual path. + // + // If the base class is not dynamic, we don't want to add it, nor any + // of its base classes. + if (!BaseDecl->isDynamicClass()) + continue; + + bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual; + bool BaseDeclIsNonVirtualPrimaryBase = false; + CharUnits BaseOffset; + if (I->isVirtual()) { + // Ignore virtual bases that we've already visited. + if (!VBases.insert(BaseDecl)) + continue; + + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + BaseDeclIsMorallyVirtual = true; + } else { + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + + BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); + + if (!Layout.isPrimaryBaseVirtual() && + Layout.getPrimaryBase() == BaseDecl) + BaseDeclIsNonVirtualPrimaryBase = true; + } + + // Itanium C++ ABI 2.6.2: + // Secondary virtual pointers: for each base class X which (a) has virtual + // bases or is reachable along a virtual path from D, and (b) is not a + // non-virtual primary base, the address of the virtual table for X-in-D + // or an appropriate construction virtual table. + if (!BaseDeclIsNonVirtualPrimaryBase && + (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) { + // Add the vtable pointer. + AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex, + VTableClass); + } + + // And lay out the secondary virtual pointers for the base class. + LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset), + BaseDeclIsMorallyVirtual, VTableIndex, + VTableClass, VBases); + } +} + +void +VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, + uint64_t VTableIndex) { + VisitedVirtualBasesSetTy VBases; + LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false, + VTableIndex, Base.getBase(), VBases); +} + +void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases) { + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Check if this is a virtual base. + if (I->isVirtual()) { + // Check if we've seen this base before. + if (!VBases.insert(BaseDecl)) + continue; + + CharUnits BaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + + LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true); + } + + // We only need to layout virtual VTTs for this base if it actually has + // virtual bases. + if (BaseDecl->getNumVBases()) + LayoutVirtualVTTs(BaseDecl, VBases); + } +} + +void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) { + const CXXRecordDecl *RD = Base.getBase(); + + // Itanium C++ ABI 2.6.2: + // An array of virtual table addresses, called the VTT, is declared for + // each class type that has indirect or direct virtual base classes. + if (RD->getNumVBases() == 0) + return; + + bool IsPrimaryVTT = Base.getBase() == MostDerivedClass; + + if (!IsPrimaryVTT) { + // Remember the sub-VTT index. + SubVTTIndicies[Base] = VTTComponents.size(); + } + + uint64_t VTableIndex = VTTVTables.size(); + VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual)); + + // Add the primary vtable pointer. + AddVTablePointer(Base, VTableIndex, RD); + + // Add the secondary VTTs. + LayoutSecondaryVTTs(Base); + + // Add the secondary virtual pointers. + LayoutSecondaryVirtualPointers(Base, VTableIndex); + + // If this is the primary VTT, we want to lay out virtual VTTs as well. + if (IsPrimaryVTT) { + VisitedVirtualBasesSetTy VBases; + LayoutVirtualVTTs(Base.getBase(), VBases); + } +} diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp new file mode 100644 index 0000000..7765817 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp @@ -0,0 +1,2404 @@ +//===--- VTableBuilder.cpp - C++ vtable layout builder --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code dealing with generation of the layout of virtual tables. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/VTableBuilder.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/RecordLayout.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/Support/Format.h" +#include <algorithm> +#include <cstdio> + +using namespace clang; + +#define DUMP_OVERRIDERS 0 + +namespace { + +/// BaseOffset - Represents an offset from a derived class to a direct or +/// indirect base class. +struct BaseOffset { + /// DerivedClass - The derived class. + const CXXRecordDecl *DerivedClass; + + /// VirtualBase - If the path from the derived class to the base class + /// involves a virtual base class, this holds its declaration. + const CXXRecordDecl *VirtualBase; + + /// NonVirtualOffset - The offset from the derived class to the base class. + /// (Or the offset from the virtual base class to the base class, if the + /// path from the derived class to the base class involves a virtual base + /// class. + CharUnits NonVirtualOffset; + + BaseOffset() : DerivedClass(0), VirtualBase(0), + NonVirtualOffset(CharUnits::Zero()) { } + BaseOffset(const CXXRecordDecl *DerivedClass, + const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset) + : DerivedClass(DerivedClass), VirtualBase(VirtualBase), + NonVirtualOffset(NonVirtualOffset) { } + + bool isEmpty() const { return NonVirtualOffset.isZero() && !VirtualBase; } +}; + +/// FinalOverriders - Contains the final overrider member functions for all +/// member functions in the base subobjects of a class. +class FinalOverriders { +public: + /// OverriderInfo - Information about a final overrider. + struct OverriderInfo { + /// Method - The method decl of the overrider. + const CXXMethodDecl *Method; + + /// Offset - the base offset of the overrider in the layout class. + CharUnits Offset; + + OverriderInfo() : Method(0), Offset(CharUnits::Zero()) { } + }; + +private: + /// MostDerivedClass - The most derived class for which the final overriders + /// are stored. + const CXXRecordDecl *MostDerivedClass; + + /// MostDerivedClassOffset - If we're building final overriders for a + /// construction vtable, this holds the offset from the layout class to the + /// most derived class. + const CharUnits MostDerivedClassOffset; + + /// LayoutClass - The class we're using for layout information. Will be + /// different than the most derived class if the final overriders are for a + /// construction vtable. + const CXXRecordDecl *LayoutClass; + + ASTContext &Context; + + /// MostDerivedClassLayout - the AST record layout of the most derived class. + const ASTRecordLayout &MostDerivedClassLayout; + + /// MethodBaseOffsetPairTy - Uniquely identifies a member function + /// in a base subobject. + typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy; + + typedef llvm::DenseMap<MethodBaseOffsetPairTy, + OverriderInfo> OverridersMapTy; + + /// OverridersMap - The final overriders for all virtual member functions of + /// all the base subobjects of the most derived class. + OverridersMapTy OverridersMap; + + /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented + /// as a record decl and a subobject number) and its offsets in the most + /// derived class as well as the layout class. + typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>, + CharUnits> SubobjectOffsetMapTy; + + typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy; + + /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the + /// given base. + void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, + CharUnits OffsetInLayoutClass, + SubobjectOffsetMapTy &SubobjectOffsets, + SubobjectOffsetMapTy &SubobjectLayoutClassOffsets, + SubobjectCountMapTy &SubobjectCounts); + + typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; + + /// dump - dump the final overriders for a base subobject, and all its direct + /// and indirect base subobjects. + void dump(raw_ostream &Out, BaseSubobject Base, + VisitedVirtualBasesSetTy& VisitedVirtualBases); + +public: + FinalOverriders(const CXXRecordDecl *MostDerivedClass, + CharUnits MostDerivedClassOffset, + const CXXRecordDecl *LayoutClass); + + /// getOverrider - Get the final overrider for the given method declaration in + /// the subobject with the given base offset. + OverriderInfo getOverrider(const CXXMethodDecl *MD, + CharUnits BaseOffset) const { + assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) && + "Did not find overrider!"); + + return OverridersMap.lookup(std::make_pair(MD, BaseOffset)); + } + + /// dump - dump the final overriders. + void dump() { + VisitedVirtualBasesSetTy VisitedVirtualBases; + dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()), + VisitedVirtualBases); + } + +}; + +#define DUMP_OVERRIDERS 0 + +FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, + CharUnits MostDerivedClassOffset, + const CXXRecordDecl *LayoutClass) + : MostDerivedClass(MostDerivedClass), + MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass), + Context(MostDerivedClass->getASTContext()), + MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) { + + // Compute base offsets. + SubobjectOffsetMapTy SubobjectOffsets; + SubobjectOffsetMapTy SubobjectLayoutClassOffsets; + SubobjectCountMapTy SubobjectCounts; + ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()), + /*IsVirtual=*/false, + MostDerivedClassOffset, + SubobjectOffsets, SubobjectLayoutClassOffsets, + SubobjectCounts); + + // Get the the final overriders. + CXXFinalOverriderMap FinalOverriders; + MostDerivedClass->getFinalOverriders(FinalOverriders); + + for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(), + E = FinalOverriders.end(); I != E; ++I) { + const CXXMethodDecl *MD = I->first; + const OverridingMethods& Methods = I->second; + + for (OverridingMethods::const_iterator I = Methods.begin(), + E = Methods.end(); I != E; ++I) { + unsigned SubobjectNumber = I->first; + assert(SubobjectOffsets.count(std::make_pair(MD->getParent(), + SubobjectNumber)) && + "Did not find subobject offset!"); + + CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(), + SubobjectNumber)]; + + assert(I->second.size() == 1 && "Final overrider is not unique!"); + const UniqueVirtualMethod &Method = I->second.front(); + + const CXXRecordDecl *OverriderRD = Method.Method->getParent(); + assert(SubobjectLayoutClassOffsets.count( + std::make_pair(OverriderRD, Method.Subobject)) + && "Did not find subobject offset!"); + CharUnits OverriderOffset = + SubobjectLayoutClassOffsets[std::make_pair(OverriderRD, + Method.Subobject)]; + + OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)]; + assert(!Overrider.Method && "Overrider should not exist yet!"); + + Overrider.Offset = OverriderOffset; + Overrider.Method = Method.Method; + } + } + +#if DUMP_OVERRIDERS + // And dump them (for now). + dump(); +#endif +} + +static BaseOffset ComputeBaseOffset(ASTContext &Context, + const CXXRecordDecl *DerivedRD, + const CXXBasePath &Path) { + CharUnits NonVirtualOffset = CharUnits::Zero(); + + unsigned NonVirtualStart = 0; + const CXXRecordDecl *VirtualBase = 0; + + // First, look for the virtual base class. + for (unsigned I = 0, E = Path.size(); I != E; ++I) { + const CXXBasePathElement &Element = Path[I]; + + if (Element.Base->isVirtual()) { + // FIXME: Can we break when we find the first virtual base? + // (If we can't, can't we just iterate over the path in reverse order?) + NonVirtualStart = I + 1; + QualType VBaseType = Element.Base->getType(); + VirtualBase = + cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl()); + } + } + + // Now compute the non-virtual offset. + for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) { + const CXXBasePathElement &Element = Path[I]; + + // Check the base class offset. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class); + + const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>(); + const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl()); + + NonVirtualOffset += Layout.getBaseClassOffset(Base); + } + + // FIXME: This should probably use CharUnits or something. Maybe we should + // even change the base offsets in ASTRecordLayout to be specified in + // CharUnits. + return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset); + +} + +static BaseOffset ComputeBaseOffset(ASTContext &Context, + const CXXRecordDecl *BaseRD, + const CXXRecordDecl *DerivedRD) { + CXXBasePaths Paths(/*FindAmbiguities=*/false, + /*RecordPaths=*/true, /*DetectVirtual=*/false); + + if (!const_cast<CXXRecordDecl *>(DerivedRD)-> + isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) { + llvm_unreachable("Class must be derived from the passed in base class!"); + } + + return ComputeBaseOffset(Context, DerivedRD, Paths.front()); +} + +static BaseOffset +ComputeReturnAdjustmentBaseOffset(ASTContext &Context, + const CXXMethodDecl *DerivedMD, + const CXXMethodDecl *BaseMD) { + const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>(); + const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>(); + + // Canonicalize the return types. + CanQualType CanDerivedReturnType = + Context.getCanonicalType(DerivedFT->getResultType()); + CanQualType CanBaseReturnType = + Context.getCanonicalType(BaseFT->getResultType()); + + assert(CanDerivedReturnType->getTypeClass() == + CanBaseReturnType->getTypeClass() && + "Types must have same type class!"); + + if (CanDerivedReturnType == CanBaseReturnType) { + // No adjustment needed. + return BaseOffset(); + } + + if (isa<ReferenceType>(CanDerivedReturnType)) { + CanDerivedReturnType = + CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType(); + CanBaseReturnType = + CanBaseReturnType->getAs<ReferenceType>()->getPointeeType(); + } else if (isa<PointerType>(CanDerivedReturnType)) { + CanDerivedReturnType = + CanDerivedReturnType->getAs<PointerType>()->getPointeeType(); + CanBaseReturnType = + CanBaseReturnType->getAs<PointerType>()->getPointeeType(); + } else { + llvm_unreachable("Unexpected return type!"); + } + + // We need to compare unqualified types here; consider + // const T *Base::foo(); + // T *Derived::foo(); + if (CanDerivedReturnType.getUnqualifiedType() == + CanBaseReturnType.getUnqualifiedType()) { + // No adjustment needed. + return BaseOffset(); + } + + const CXXRecordDecl *DerivedRD = + cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl()); + + const CXXRecordDecl *BaseRD = + cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl()); + + return ComputeBaseOffset(Context, BaseRD, DerivedRD); +} + +void +FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, + CharUnits OffsetInLayoutClass, + SubobjectOffsetMapTy &SubobjectOffsets, + SubobjectOffsetMapTy &SubobjectLayoutClassOffsets, + SubobjectCountMapTy &SubobjectCounts) { + const CXXRecordDecl *RD = Base.getBase(); + + unsigned SubobjectNumber = 0; + if (!IsVirtual) + SubobjectNumber = ++SubobjectCounts[RD]; + + // Set up the subobject to offset mapping. + assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber)) + && "Subobject offset already exists!"); + assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber)) + && "Subobject offset already exists!"); + + SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.getBaseOffset(); + SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] = + OffsetInLayoutClass; + + // Traverse our bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + CharUnits BaseOffset; + CharUnits BaseOffsetInLayoutClass; + if (I->isVirtual()) { + // Check if we've visited this virtual base before. + if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0))) + continue; + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + BaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(BaseDecl); + } else { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + CharUnits Offset = Layout.getBaseClassOffset(BaseDecl); + + BaseOffset = Base.getBaseOffset() + Offset; + BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset; + } + + ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset), + I->isVirtual(), BaseOffsetInLayoutClass, + SubobjectOffsets, SubobjectLayoutClassOffsets, + SubobjectCounts); + } +} + +void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base, + VisitedVirtualBasesSetTy &VisitedVirtualBases) { + const CXXRecordDecl *RD = Base.getBase(); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Ignore bases that don't have any virtual member functions. + if (!BaseDecl->isPolymorphic()) + continue; + + CharUnits BaseOffset; + if (I->isVirtual()) { + if (!VisitedVirtualBases.insert(BaseDecl)) { + // We've visited this base before. + continue; + } + + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + } else { + BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset(); + } + + dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases); + } + + Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", "; + Out << Base.getBaseOffset().getQuantity() << ")\n"; + + // Now dump the overriders for this base subobject. + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + const CXXMethodDecl *MD = *I; + + if (!MD->isVirtual()) + continue; + + OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset()); + + Out << " " << MD->getQualifiedNameAsString() << " - ("; + Out << Overrider.Method->getQualifiedNameAsString(); + Out << ", " << ", " << Overrider.Offset.getQuantity() << ')'; + + BaseOffset Offset; + if (!Overrider.Method->isPure()) + Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD); + + if (!Offset.isEmpty()) { + Out << " [ret-adj: "; + if (Offset.VirtualBase) + Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, "; + + Out << Offset.NonVirtualOffset.getQuantity() << " nv]"; + } + + Out << "\n"; + } +} + +/// VCallOffsetMap - Keeps track of vcall offsets when building a vtable. +struct VCallOffsetMap { + + typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy; + + /// Offsets - Keeps track of methods and their offsets. + // FIXME: This should be a real map and not a vector. + SmallVector<MethodAndOffsetPairTy, 16> Offsets; + + /// MethodsCanShareVCallOffset - Returns whether two virtual member functions + /// can share the same vcall offset. + static bool MethodsCanShareVCallOffset(const CXXMethodDecl *LHS, + const CXXMethodDecl *RHS); + +public: + /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the + /// add was successful, or false if there was already a member function with + /// the same signature in the map. + bool AddVCallOffset(const CXXMethodDecl *MD, CharUnits OffsetOffset); + + /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the + /// vtable address point) for the given virtual member function. + CharUnits getVCallOffsetOffset(const CXXMethodDecl *MD); + + // empty - Return whether the offset map is empty or not. + bool empty() const { return Offsets.empty(); } +}; + +static bool HasSameVirtualSignature(const CXXMethodDecl *LHS, + const CXXMethodDecl *RHS) { + ASTContext &C = LHS->getASTContext(); // TODO: thread this down + CanQual<FunctionProtoType> + LT = C.getCanonicalType(LHS->getType()).getAs<FunctionProtoType>(), + RT = C.getCanonicalType(RHS->getType()).getAs<FunctionProtoType>(); + + // Fast-path matches in the canonical types. + if (LT == RT) return true; + + // Force the signatures to match. We can't rely on the overrides + // list here because there isn't necessarily an inheritance + // relationship between the two methods. + if (LT.getQualifiers() != RT.getQualifiers() || + LT->getNumArgs() != RT->getNumArgs()) + return false; + for (unsigned I = 0, E = LT->getNumArgs(); I != E; ++I) + if (LT->getArgType(I) != RT->getArgType(I)) + return false; + return true; +} + +bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS, + const CXXMethodDecl *RHS) { + assert(LHS->isVirtual() && "LHS must be virtual!"); + assert(RHS->isVirtual() && "LHS must be virtual!"); + + // A destructor can share a vcall offset with another destructor. + if (isa<CXXDestructorDecl>(LHS)) + return isa<CXXDestructorDecl>(RHS); + + // FIXME: We need to check more things here. + + // The methods must have the same name. + DeclarationName LHSName = LHS->getDeclName(); + DeclarationName RHSName = RHS->getDeclName(); + if (LHSName != RHSName) + return false; + + // And the same signatures. + return HasSameVirtualSignature(LHS, RHS); +} + +bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD, + CharUnits OffsetOffset) { + // Check if we can reuse an offset. + for (unsigned I = 0, E = Offsets.size(); I != E; ++I) { + if (MethodsCanShareVCallOffset(Offsets[I].first, MD)) + return false; + } + + // Add the offset. + Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset)); + return true; +} + +CharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) { + // Look for an offset. + for (unsigned I = 0, E = Offsets.size(); I != E; ++I) { + if (MethodsCanShareVCallOffset(Offsets[I].first, MD)) + return Offsets[I].second; + } + + llvm_unreachable("Should always find a vcall offset offset!"); +} + +/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets. +class VCallAndVBaseOffsetBuilder { +public: + typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> + VBaseOffsetOffsetsMapTy; + +private: + /// MostDerivedClass - The most derived class for which we're building vcall + /// and vbase offsets. + const CXXRecordDecl *MostDerivedClass; + + /// LayoutClass - The class we're using for layout information. Will be + /// different than the most derived class if we're building a construction + /// vtable. + const CXXRecordDecl *LayoutClass; + + /// Context - The ASTContext which we will use for layout information. + ASTContext &Context; + + /// Components - vcall and vbase offset components + typedef SmallVector<VTableComponent, 64> VTableComponentVectorTy; + VTableComponentVectorTy Components; + + /// VisitedVirtualBases - Visited virtual bases. + llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases; + + /// VCallOffsets - Keeps track of vcall offsets. + VCallOffsetMap VCallOffsets; + + + /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets, + /// relative to the address point. + VBaseOffsetOffsetsMapTy VBaseOffsetOffsets; + + /// FinalOverriders - The final overriders of the most derived class. + /// (Can be null when we're not building a vtable of the most derived class). + const FinalOverriders *Overriders; + + /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the + /// given base subobject. + void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual, + CharUnits RealBaseOffset); + + /// AddVCallOffsets - Add vcall offsets for the given base subobject. + void AddVCallOffsets(BaseSubobject Base, CharUnits VBaseOffset); + + /// AddVBaseOffsets - Add vbase offsets for the given class. + void AddVBaseOffsets(const CXXRecordDecl *Base, + CharUnits OffsetInLayoutClass); + + /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in + /// chars, relative to the vtable address point. + CharUnits getCurrentOffsetOffset() const; + +public: + VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass, + const CXXRecordDecl *LayoutClass, + const FinalOverriders *Overriders, + BaseSubobject Base, bool BaseIsVirtual, + CharUnits OffsetInLayoutClass) + : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass), + Context(MostDerivedClass->getASTContext()), Overriders(Overriders) { + + // Add vcall and vbase offsets. + AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass); + } + + /// Methods for iterating over the components. + typedef VTableComponentVectorTy::const_reverse_iterator const_iterator; + const_iterator components_begin() const { return Components.rbegin(); } + const_iterator components_end() const { return Components.rend(); } + + const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; } + const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const { + return VBaseOffsetOffsets; + } +}; + +void +VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base, + bool BaseIsVirtual, + CharUnits RealBaseOffset) { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase()); + + // Itanium C++ ABI 2.5.2: + // ..in classes sharing a virtual table with a primary base class, the vcall + // and vbase offsets added by the derived class all come before the vcall + // and vbase offsets required by the base class, so that the latter may be + // laid out as required by the base class without regard to additions from + // the derived class(es). + + // (Since we're emitting the vcall and vbase offsets in reverse order, we'll + // emit them for the primary base first). + if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) { + bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual(); + + CharUnits PrimaryBaseOffset; + + // Get the base offset of the primary base. + if (PrimaryBaseIsVirtual) { + assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 && + "Primary vbase should have a zero offset!"); + + const ASTRecordLayout &MostDerivedClassLayout = + Context.getASTRecordLayout(MostDerivedClass); + + PrimaryBaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase); + } else { + assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 && + "Primary base should have a zero offset!"); + + PrimaryBaseOffset = Base.getBaseOffset(); + } + + AddVCallAndVBaseOffsets( + BaseSubobject(PrimaryBase,PrimaryBaseOffset), + PrimaryBaseIsVirtual, RealBaseOffset); + } + + AddVBaseOffsets(Base.getBase(), RealBaseOffset); + + // We only want to add vcall offsets for virtual bases. + if (BaseIsVirtual) + AddVCallOffsets(Base, RealBaseOffset); +} + +CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const { + // OffsetIndex is the index of this vcall or vbase offset, relative to the + // vtable address point. (We subtract 3 to account for the information just + // above the address point, the RTTI info, the offset to top, and the + // vcall offset itself). + int64_t OffsetIndex = -(int64_t)(3 + Components.size()); + + CharUnits PointerWidth = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); + CharUnits OffsetOffset = PointerWidth * OffsetIndex; + return OffsetOffset; +} + +void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, + CharUnits VBaseOffset) { + const CXXRecordDecl *RD = Base.getBase(); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + + // Handle the primary base first. + // We only want to add vcall offsets if the base is non-virtual; a virtual + // primary base will have its vcall and vbase offsets emitted already. + if (PrimaryBase && !Layout.isPrimaryBaseVirtual()) { + // Get the base offset of the primary base. + assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 && + "Primary base should have a zero offset!"); + + AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()), + VBaseOffset); + } + + // Add the vcall offsets. + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + const CXXMethodDecl *MD = *I; + + if (!MD->isVirtual()) + continue; + + CharUnits OffsetOffset = getCurrentOffsetOffset(); + + // Don't add a vcall offset if we already have one for this member function + // signature. + if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset)) + continue; + + CharUnits Offset = CharUnits::Zero(); + + if (Overriders) { + // Get the final overrider. + FinalOverriders::OverriderInfo Overrider = + Overriders->getOverrider(MD, Base.getBaseOffset()); + + /// The vcall offset is the offset from the virtual base to the object + /// where the function was overridden. + Offset = Overrider.Offset - VBaseOffset; + } + + Components.push_back( + VTableComponent::MakeVCallOffset(Offset)); + } + + // And iterate over all non-virtual bases (ignoring the primary base). + 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()); + if (BaseDecl == PrimaryBase) + continue; + + // Get the base offset of this base. + CharUnits BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); + + AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset), + VBaseOffset); + } +} + +void +VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, + CharUnits OffsetInLayoutClass) { + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + // Add vbase offsets. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Check if this is a virtual base that we haven't visited before. + if (I->isVirtual() && VisitedVirtualBases.insert(BaseDecl)) { + CharUnits Offset = + LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass; + + // Add the vbase offset offset. + assert(!VBaseOffsetOffsets.count(BaseDecl) && + "vbase offset offset already exists!"); + + CharUnits VBaseOffsetOffset = getCurrentOffsetOffset(); + VBaseOffsetOffsets.insert( + std::make_pair(BaseDecl, VBaseOffsetOffset)); + + Components.push_back( + VTableComponent::MakeVBaseOffset(Offset)); + } + + // Check the base class looking for more vbase offsets. + AddVBaseOffsets(BaseDecl, OffsetInLayoutClass); + } +} + +/// VTableBuilder - Class for building vtable layout information. +class VTableBuilder { +public: + /// PrimaryBasesSetVectorTy - A set vector of direct and indirect + /// primary bases. + typedef llvm::SmallSetVector<const CXXRecordDecl *, 8> + PrimaryBasesSetVectorTy; + + typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> + VBaseOffsetOffsetsMapTy; + + typedef llvm::DenseMap<BaseSubobject, uint64_t> + AddressPointsMapTy; + +private: + /// VTables - Global vtable information. + VTableContext &VTables; + + /// MostDerivedClass - The most derived class for which we're building this + /// vtable. + const CXXRecordDecl *MostDerivedClass; + + /// MostDerivedClassOffset - If we're building a construction vtable, this + /// holds the offset from the layout class to the most derived class. + const CharUnits MostDerivedClassOffset; + + /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual + /// base. (This only makes sense when building a construction vtable). + bool MostDerivedClassIsVirtual; + + /// LayoutClass - The class we're using for layout information. Will be + /// different than the most derived class if we're building a construction + /// vtable. + const CXXRecordDecl *LayoutClass; + + /// Context - The ASTContext which we will use for layout information. + ASTContext &Context; + + /// FinalOverriders - The final overriders of the most derived class. + const FinalOverriders Overriders; + + /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual + /// bases in this vtable. + llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases; + + /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for + /// the most derived class. + VBaseOffsetOffsetsMapTy VBaseOffsetOffsets; + + /// Components - The components of the vtable being built. + SmallVector<VTableComponent, 64> Components; + + /// AddressPoints - Address points for the vtable being built. + AddressPointsMapTy AddressPoints; + + /// MethodInfo - Contains information about a method in a vtable. + /// (Used for computing 'this' pointer adjustment thunks. + struct MethodInfo { + /// BaseOffset - The base offset of this method. + const CharUnits BaseOffset; + + /// BaseOffsetInLayoutClass - The base offset in the layout class of this + /// method. + const CharUnits BaseOffsetInLayoutClass; + + /// VTableIndex - The index in the vtable that this method has. + /// (For destructors, this is the index of the complete destructor). + const uint64_t VTableIndex; + + MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass, + uint64_t VTableIndex) + : BaseOffset(BaseOffset), + BaseOffsetInLayoutClass(BaseOffsetInLayoutClass), + VTableIndex(VTableIndex) { } + + MethodInfo() + : BaseOffset(CharUnits::Zero()), + BaseOffsetInLayoutClass(CharUnits::Zero()), + VTableIndex(0) { } + }; + + typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy; + + /// MethodInfoMap - The information for all methods in the vtable we're + /// currently building. + MethodInfoMapTy MethodInfoMap; + + typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy; + + /// VTableThunks - The thunks by vtable index in the vtable currently being + /// built. + VTableThunksMapTy VTableThunks; + + typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; + typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy; + + /// Thunks - A map that contains all the thunks needed for all methods in the + /// most derived class for which the vtable is currently being built. + ThunksMapTy Thunks; + + /// AddThunk - Add a thunk for the given method. + void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk); + + /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the + /// part of the vtable we're currently building. + void ComputeThisAdjustments(); + + typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; + + /// PrimaryVirtualBases - All known virtual bases who are a primary base of + /// some other base. + VisitedVirtualBasesSetTy PrimaryVirtualBases; + + /// ComputeReturnAdjustment - Compute the return adjustment given a return + /// adjustment base offset. + ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset); + + /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting + /// the 'this' pointer from the base subobject to the derived subobject. + BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base, + BaseSubobject Derived) const; + + /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the + /// given virtual member function, its offset in the layout class and its + /// final overrider. + ThisAdjustment + ComputeThisAdjustment(const CXXMethodDecl *MD, + CharUnits BaseOffsetInLayoutClass, + FinalOverriders::OverriderInfo Overrider); + + /// AddMethod - Add a single virtual member function to the vtable + /// components vector. + void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment); + + /// IsOverriderUsed - Returns whether the overrider will ever be used in this + /// part of the vtable. + /// + /// Itanium C++ ABI 2.5.2: + /// + /// struct A { virtual void f(); }; + /// struct B : virtual public A { int i; }; + /// struct C : virtual public A { int j; }; + /// struct D : public B, public C {}; + /// + /// When B and C are declared, A is a primary base in each case, so although + /// vcall offsets are allocated in the A-in-B and A-in-C vtables, no this + /// adjustment is required and no thunk is generated. However, inside D + /// objects, A is no longer a primary base of C, so if we allowed calls to + /// C::f() to use the copy of A's vtable in the C subobject, we would need + /// to adjust this from C* to B::A*, which would require a third-party + /// thunk. Since we require that a call to C::f() first convert to A*, + /// C-in-D's copy of A's vtable is never referenced, so this is not + /// necessary. + bool IsOverriderUsed(const CXXMethodDecl *Overrider, + CharUnits BaseOffsetInLayoutClass, + const CXXRecordDecl *FirstBaseInPrimaryBaseChain, + CharUnits FirstBaseOffsetInLayoutClass) const; + + + /// AddMethods - Add the methods of this base subobject and all its + /// primary bases to the vtable components vector. + void AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass, + const CXXRecordDecl *FirstBaseInPrimaryBaseChain, + CharUnits FirstBaseOffsetInLayoutClass, + PrimaryBasesSetVectorTy &PrimaryBases); + + // LayoutVTable - Layout the vtable for the given base class, including its + // secondary vtables and any vtables for virtual bases. + void LayoutVTable(); + + /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the + /// given base subobject, as well as all its secondary vtables. + /// + /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base + /// or a direct or indirect base of a virtual base. + /// + /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual + /// in the layout class. + void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, + bool BaseIsMorallyVirtual, + bool BaseIsVirtualInLayoutClass, + CharUnits OffsetInLayoutClass); + + /// LayoutSecondaryVTables - Layout the secondary vtables for the given base + /// subobject. + /// + /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base + /// or a direct or indirect base of a virtual base. + void LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual, + CharUnits OffsetInLayoutClass); + + /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this + /// class hierarchy. + void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, + CharUnits OffsetInLayoutClass, + VisitedVirtualBasesSetTy &VBases); + + /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the + /// given base (excluding any primary bases). + void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases); + + /// isBuildingConstructionVTable - Return whether this vtable builder is + /// building a construction vtable. + bool isBuildingConstructorVTable() const { + return MostDerivedClass != LayoutClass; + } + +public: + VTableBuilder(VTableContext &VTables, const CXXRecordDecl *MostDerivedClass, + CharUnits MostDerivedClassOffset, + bool MostDerivedClassIsVirtual, const + CXXRecordDecl *LayoutClass) + : VTables(VTables), MostDerivedClass(MostDerivedClass), + MostDerivedClassOffset(MostDerivedClassOffset), + MostDerivedClassIsVirtual(MostDerivedClassIsVirtual), + LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), + Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) { + + LayoutVTable(); + + if (Context.getLangOptions().DumpVTableLayouts) + dumpLayout(llvm::errs()); + } + + uint64_t getNumThunks() const { + return Thunks.size(); + } + + ThunksMapTy::const_iterator thunks_begin() const { + return Thunks.begin(); + } + + ThunksMapTy::const_iterator thunks_end() const { + return Thunks.end(); + } + + const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const { + return VBaseOffsetOffsets; + } + + const AddressPointsMapTy &getAddressPoints() const { + return AddressPoints; + } + + /// getNumVTableComponents - Return the number of components in the vtable + /// currently built. + uint64_t getNumVTableComponents() const { + return Components.size(); + } + + const VTableComponent *vtable_component_begin() const { + return Components.begin(); + } + + const VTableComponent *vtable_component_end() const { + return Components.end(); + } + + AddressPointsMapTy::const_iterator address_points_begin() const { + return AddressPoints.begin(); + } + + AddressPointsMapTy::const_iterator address_points_end() const { + return AddressPoints.end(); + } + + VTableThunksMapTy::const_iterator vtable_thunks_begin() const { + return VTableThunks.begin(); + } + + VTableThunksMapTy::const_iterator vtable_thunks_end() const { + return VTableThunks.end(); + } + + /// dumpLayout - Dump the vtable layout. + void dumpLayout(raw_ostream&); +}; + +void VTableBuilder::AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) { + assert(!isBuildingConstructorVTable() && + "Can't add thunks for construction vtable"); + + SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD]; + + // Check if we have this thunk already. + if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) != + ThunksVector.end()) + return; + + ThunksVector.push_back(Thunk); +} + +typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy; + +/// ComputeAllOverriddenMethods - Given a method decl, will return a set of all +/// the overridden methods that the function decl overrides. +static void +ComputeAllOverriddenMethods(const CXXMethodDecl *MD, + OverriddenMethodsSetTy& OverriddenMethods) { + assert(MD->isVirtual() && "Method is not virtual!"); + + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); I != E; ++I) { + const CXXMethodDecl *OverriddenMD = *I; + + OverriddenMethods.insert(OverriddenMD); + + ComputeAllOverriddenMethods(OverriddenMD, OverriddenMethods); + } +} + +void VTableBuilder::ComputeThisAdjustments() { + // Now go through the method info map and see if any of the methods need + // 'this' pointer adjustments. + for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(), + E = MethodInfoMap.end(); I != E; ++I) { + const CXXMethodDecl *MD = I->first; + const MethodInfo &MethodInfo = I->second; + + // Ignore adjustments for unused function pointers. + uint64_t VTableIndex = MethodInfo.VTableIndex; + if (Components[VTableIndex].getKind() == + VTableComponent::CK_UnusedFunctionPointer) + continue; + + // Get the final overrider for this method. + FinalOverriders::OverriderInfo Overrider = + Overriders.getOverrider(MD, MethodInfo.BaseOffset); + + // Check if we need an adjustment at all. + if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) { + // When a return thunk is needed by a derived class that overrides a + // virtual base, gcc uses a virtual 'this' adjustment as well. + // While the thunk itself might be needed by vtables in subclasses or + // in construction vtables, there doesn't seem to be a reason for using + // the thunk in this vtable. Still, we do so to match gcc. + if (VTableThunks.lookup(VTableIndex).Return.isEmpty()) + continue; + } + + ThisAdjustment ThisAdjustment = + ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider); + + if (ThisAdjustment.isEmpty()) + continue; + + // Add it. + VTableThunks[VTableIndex].This = ThisAdjustment; + + if (isa<CXXDestructorDecl>(MD)) { + // Add an adjustment for the deleting destructor as well. + VTableThunks[VTableIndex + 1].This = ThisAdjustment; + } + } + + /// Clear the method info map. + MethodInfoMap.clear(); + + if (isBuildingConstructorVTable()) { + // We don't need to store thunk information for construction vtables. + return; + } + + for (VTableThunksMapTy::const_iterator I = VTableThunks.begin(), + E = VTableThunks.end(); I != E; ++I) { + const VTableComponent &Component = Components[I->first]; + const ThunkInfo &Thunk = I->second; + const CXXMethodDecl *MD; + + switch (Component.getKind()) { + default: + llvm_unreachable("Unexpected vtable component kind!"); + case VTableComponent::CK_FunctionPointer: + MD = Component.getFunctionDecl(); + break; + case VTableComponent::CK_CompleteDtorPointer: + MD = Component.getDestructorDecl(); + break; + case VTableComponent::CK_DeletingDtorPointer: + // We've already added the thunk when we saw the complete dtor pointer. + continue; + } + + if (MD->getParent() == MostDerivedClass) + AddThunk(MD, Thunk); + } +} + +ReturnAdjustment VTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) { + ReturnAdjustment Adjustment; + + if (!Offset.isEmpty()) { + if (Offset.VirtualBase) { + // Get the virtual base offset offset. + if (Offset.DerivedClass == MostDerivedClass) { + // We can get the offset offset directly from our map. + Adjustment.VBaseOffsetOffset = + VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity(); + } else { + Adjustment.VBaseOffsetOffset = + VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass, + Offset.VirtualBase).getQuantity(); + } + } + + Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity(); + } + + return Adjustment; +} + +BaseOffset +VTableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base, + BaseSubobject Derived) const { + const CXXRecordDecl *BaseRD = Base.getBase(); + const CXXRecordDecl *DerivedRD = Derived.getBase(); + + CXXBasePaths Paths(/*FindAmbiguities=*/true, + /*RecordPaths=*/true, /*DetectVirtual=*/true); + + if (!const_cast<CXXRecordDecl *>(DerivedRD)-> + isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) { + llvm_unreachable("Class must be derived from the passed in base class!"); + } + + // We have to go through all the paths, and see which one leads us to the + // right base subobject. + for (CXXBasePaths::const_paths_iterator I = Paths.begin(), E = Paths.end(); + I != E; ++I) { + BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I); + + CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset; + + if (Offset.VirtualBase) { + // If we have a virtual base class, the non-virtual offset is relative + // to the virtual base class offset. + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + /// Get the virtual base offset, relative to the most derived class + /// layout. + OffsetToBaseSubobject += + LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase); + } else { + // Otherwise, the non-virtual offset is relative to the derived class + // offset. + OffsetToBaseSubobject += Derived.getBaseOffset(); + } + + // Check if this path gives us the right base subobject. + if (OffsetToBaseSubobject == Base.getBaseOffset()) { + // Since we're going from the base class _to_ the derived class, we'll + // invert the non-virtual offset here. + Offset.NonVirtualOffset = -Offset.NonVirtualOffset; + return Offset; + } + } + + return BaseOffset(); +} + +ThisAdjustment +VTableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD, + CharUnits BaseOffsetInLayoutClass, + FinalOverriders::OverriderInfo Overrider) { + // Ignore adjustments for pure virtual member functions. + if (Overrider.Method->isPure()) + return ThisAdjustment(); + + BaseSubobject OverriddenBaseSubobject(MD->getParent(), + BaseOffsetInLayoutClass); + + BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(), + Overrider.Offset); + + // Compute the adjustment offset. + BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject, + OverriderBaseSubobject); + if (Offset.isEmpty()) + return ThisAdjustment(); + + ThisAdjustment Adjustment; + + if (Offset.VirtualBase) { + // Get the vcall offset map for this virtual base. + VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase]; + + if (VCallOffsets.empty()) { + // We don't have vcall offsets for this virtual base, go ahead and + // build them. + VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass, + /*FinalOverriders=*/0, + BaseSubobject(Offset.VirtualBase, + CharUnits::Zero()), + /*BaseIsVirtual=*/true, + /*OffsetInLayoutClass=*/ + CharUnits::Zero()); + + VCallOffsets = Builder.getVCallOffsets(); + } + + Adjustment.VCallOffsetOffset = + VCallOffsets.getVCallOffsetOffset(MD).getQuantity(); + } + + // Set the non-virtual part of the adjustment. + Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity(); + + return Adjustment; +} + +void +VTableBuilder::AddMethod(const CXXMethodDecl *MD, + ReturnAdjustment ReturnAdjustment) { + if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { + assert(ReturnAdjustment.isEmpty() && + "Destructor can't have return adjustment!"); + + // Add both the complete destructor and the deleting destructor. + Components.push_back(VTableComponent::MakeCompleteDtor(DD)); + Components.push_back(VTableComponent::MakeDeletingDtor(DD)); + } else { + // Add the return adjustment if necessary. + if (!ReturnAdjustment.isEmpty()) + VTableThunks[Components.size()].Return = ReturnAdjustment; + + // Add the function. + Components.push_back(VTableComponent::MakeFunction(MD)); + } +} + +/// OverridesIndirectMethodInBase - Return whether the given member function +/// overrides any methods in the set of given bases. +/// Unlike OverridesMethodInBase, this checks "overriders of overriders". +/// For example, if we have: +/// +/// struct A { virtual void f(); } +/// struct B : A { virtual void f(); } +/// struct C : B { virtual void f(); } +/// +/// OverridesIndirectMethodInBase will return true if given C::f as the method +/// and { A } as the set of bases. +static bool +OverridesIndirectMethodInBases(const CXXMethodDecl *MD, + VTableBuilder::PrimaryBasesSetVectorTy &Bases) { + if (Bases.count(MD->getParent())) + return true; + + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); I != E; ++I) { + const CXXMethodDecl *OverriddenMD = *I; + + // Check "indirect overriders". + if (OverridesIndirectMethodInBases(OverriddenMD, Bases)) + return true; + } + + return false; +} + +bool +VTableBuilder::IsOverriderUsed(const CXXMethodDecl *Overrider, + CharUnits BaseOffsetInLayoutClass, + const CXXRecordDecl *FirstBaseInPrimaryBaseChain, + CharUnits FirstBaseOffsetInLayoutClass) const { + // If the base and the first base in the primary base chain have the same + // offsets, then this overrider will be used. + if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass) + return true; + + // We know now that Base (or a direct or indirect base of it) is a primary + // base in part of the class hierarchy, but not a primary base in the most + // derived class. + + // If the overrider is the first base in the primary base chain, we know + // that the overrider will be used. + if (Overrider->getParent() == FirstBaseInPrimaryBaseChain) + return true; + + VTableBuilder::PrimaryBasesSetVectorTy PrimaryBases; + + const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain; + PrimaryBases.insert(RD); + + // Now traverse the base chain, starting with the first base, until we find + // the base that is no longer a primary base. + while (true) { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + + if (!PrimaryBase) + break; + + if (Layout.isPrimaryBaseVirtual()) { + assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 && + "Primary base should always be at offset 0!"); + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + // Now check if this is the primary base that is not a primary base in the + // most derived class. + if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) != + FirstBaseOffsetInLayoutClass) { + // We found it, stop walking the chain. + break; + } + } else { + assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 && + "Primary base should always be at offset 0!"); + } + + if (!PrimaryBases.insert(PrimaryBase)) + llvm_unreachable("Found a duplicate primary base!"); + + RD = PrimaryBase; + } + + // If the final overrider is an override of one of the primary bases, + // then we know that it will be used. + return OverridesIndirectMethodInBases(Overrider, PrimaryBases); +} + +/// FindNearestOverriddenMethod - Given a method, returns the overridden method +/// from the nearest base. Returns null if no method was found. +static const CXXMethodDecl * +FindNearestOverriddenMethod(const CXXMethodDecl *MD, + VTableBuilder::PrimaryBasesSetVectorTy &Bases) { + OverriddenMethodsSetTy OverriddenMethods; + ComputeAllOverriddenMethods(MD, OverriddenMethods); + + for (int I = Bases.size(), E = 0; I != E; --I) { + const CXXRecordDecl *PrimaryBase = Bases[I - 1]; + + // Now check the overriden methods. + for (OverriddenMethodsSetTy::const_iterator I = OverriddenMethods.begin(), + E = OverriddenMethods.end(); I != E; ++I) { + const CXXMethodDecl *OverriddenMD = *I; + + // We found our overridden method. + if (OverriddenMD->getParent() == PrimaryBase) + return OverriddenMD; + } + } + + return 0; +} + +void +VTableBuilder::AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass, + const CXXRecordDecl *FirstBaseInPrimaryBaseChain, + CharUnits FirstBaseOffsetInLayoutClass, + PrimaryBasesSetVectorTy &PrimaryBases) { + const CXXRecordDecl *RD = Base.getBase(); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) { + CharUnits PrimaryBaseOffset; + CharUnits PrimaryBaseOffsetInLayoutClass; + if (Layout.isPrimaryBaseVirtual()) { + assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 && + "Primary vbase should have a zero offset!"); + + const ASTRecordLayout &MostDerivedClassLayout = + Context.getASTRecordLayout(MostDerivedClass); + + PrimaryBaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase); + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + PrimaryBaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(PrimaryBase); + } else { + assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 && + "Primary base should have a zero offset!"); + + PrimaryBaseOffset = Base.getBaseOffset(); + PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass; + } + + AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset), + PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain, + FirstBaseOffsetInLayoutClass, PrimaryBases); + + if (!PrimaryBases.insert(PrimaryBase)) + llvm_unreachable("Found a duplicate primary base!"); + } + + // Now go through all virtual member functions and add them. + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + const CXXMethodDecl *MD = *I; + + if (!MD->isVirtual()) + continue; + + // Get the final overrider. + FinalOverriders::OverriderInfo Overrider = + Overriders.getOverrider(MD, Base.getBaseOffset()); + + // Check if this virtual member function overrides a method in a primary + // base. If this is the case, and the return type doesn't require adjustment + // then we can just use the member function from the primary base. + if (const CXXMethodDecl *OverriddenMD = + FindNearestOverriddenMethod(MD, PrimaryBases)) { + if (ComputeReturnAdjustmentBaseOffset(Context, MD, + OverriddenMD).isEmpty()) { + // Replace the method info of the overridden method with our own + // method. + assert(MethodInfoMap.count(OverriddenMD) && + "Did not find the overridden method!"); + MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD]; + + MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass, + OverriddenMethodInfo.VTableIndex); + + assert(!MethodInfoMap.count(MD) && + "Should not have method info for this method yet!"); + + MethodInfoMap.insert(std::make_pair(MD, MethodInfo)); + MethodInfoMap.erase(OverriddenMD); + + // If the overridden method exists in a virtual base class or a direct + // or indirect base class of a virtual base class, we need to emit a + // thunk if we ever have a class hierarchy where the base class is not + // a primary base in the complete object. + if (!isBuildingConstructorVTable() && OverriddenMD != MD) { + // Compute the this adjustment. + ThisAdjustment ThisAdjustment = + ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass, + Overrider); + + if (ThisAdjustment.VCallOffsetOffset && + Overrider.Method->getParent() == MostDerivedClass) { + + // There's no return adjustment from OverriddenMD and MD, + // but that doesn't mean there isn't one between MD and + // the final overrider. + BaseOffset ReturnAdjustmentOffset = + ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD); + ReturnAdjustment ReturnAdjustment = + ComputeReturnAdjustment(ReturnAdjustmentOffset); + + // This is a virtual thunk for the most derived class, add it. + AddThunk(Overrider.Method, + ThunkInfo(ThisAdjustment, ReturnAdjustment)); + } + } + + continue; + } + } + + // Insert the method info for this method. + MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass, + Components.size()); + + assert(!MethodInfoMap.count(MD) && + "Should not have method info for this method yet!"); + MethodInfoMap.insert(std::make_pair(MD, MethodInfo)); + + // Check if this overrider is going to be used. + const CXXMethodDecl *OverriderMD = Overrider.Method; + if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass, + FirstBaseInPrimaryBaseChain, + FirstBaseOffsetInLayoutClass)) { + Components.push_back(VTableComponent::MakeUnusedFunction(OverriderMD)); + continue; + } + + // Check if this overrider needs a return adjustment. + // We don't want to do this for pure virtual member functions. + BaseOffset ReturnAdjustmentOffset; + if (!OverriderMD->isPure()) { + ReturnAdjustmentOffset = + ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD); + } + + ReturnAdjustment ReturnAdjustment = + ComputeReturnAdjustment(ReturnAdjustmentOffset); + + AddMethod(Overrider.Method, ReturnAdjustment); + } +} + +void VTableBuilder::LayoutVTable() { + LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass, + CharUnits::Zero()), + /*BaseIsMorallyVirtual=*/false, + MostDerivedClassIsVirtual, + MostDerivedClassOffset); + + VisitedVirtualBasesSetTy VBases; + + // Determine the primary virtual bases. + DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset, + VBases); + VBases.clear(); + + LayoutVTablesForVirtualBases(MostDerivedClass, VBases); + + // -fapple-kext adds an extra entry at end of vtbl. + bool IsAppleKext = Context.getLangOptions().AppleKext; + if (IsAppleKext) + Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero())); +} + +void +VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, + bool BaseIsMorallyVirtual, + bool BaseIsVirtualInLayoutClass, + CharUnits OffsetInLayoutClass) { + assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!"); + + // Add vcall and vbase offsets for this vtable. + VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders, + Base, BaseIsVirtualInLayoutClass, + OffsetInLayoutClass); + Components.append(Builder.components_begin(), Builder.components_end()); + + // Check if we need to add these vcall offsets. + if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) { + VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()]; + + if (VCallOffsets.empty()) + VCallOffsets = Builder.getVCallOffsets(); + } + + // If we're laying out the most derived class we want to keep track of the + // virtual base class offset offsets. + if (Base.getBase() == MostDerivedClass) + VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets(); + + // Add the offset to top. + CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass; + Components.push_back( + VTableComponent::MakeOffsetToTop(OffsetToTop)); + + // Next, add the RTTI. + Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass)); + + uint64_t AddressPoint = Components.size(); + + // Now go through all virtual member functions and add them. + PrimaryBasesSetVectorTy PrimaryBases; + AddMethods(Base, OffsetInLayoutClass, + Base.getBase(), OffsetInLayoutClass, + PrimaryBases); + + // Compute 'this' pointer adjustments. + ComputeThisAdjustments(); + + // Add all address points. + const CXXRecordDecl *RD = Base.getBase(); + while (true) { + AddressPoints.insert(std::make_pair( + BaseSubobject(RD, OffsetInLayoutClass), + AddressPoint)); + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + + if (!PrimaryBase) + break; + + if (Layout.isPrimaryBaseVirtual()) { + // Check if this virtual primary base is a primary base in the layout + // class. If it's not, we don't want to add it. + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) != + OffsetInLayoutClass) { + // We don't want to add this class (or any of its primary bases). + break; + } + } + + RD = PrimaryBase; + } + + // Layout secondary vtables. + LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass); +} + +void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base, + bool BaseIsMorallyVirtual, + CharUnits OffsetInLayoutClass) { + // Itanium C++ ABI 2.5.2: + // Following the primary virtual table of a derived class are secondary + // virtual tables for each of its proper base classes, except any primary + // base(s) with which it shares its primary virtual table. + + const CXXRecordDecl *RD = Base.getBase(); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + // Ignore virtual bases, we'll emit them later. + if (I->isVirtual()) + continue; + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Ignore bases that don't have a vtable. + if (!BaseDecl->isDynamicClass()) + continue; + + if (isBuildingConstructorVTable()) { + // Itanium C++ ABI 2.6.4: + // Some of the base class subobjects may not need construction virtual + // tables, which will therefore not be present in the construction + // virtual table group, even though the subobject virtual tables are + // present in the main virtual table group for the complete object. + if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases()) + continue; + } + + // Get the base offset of this base. + CharUnits RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl); + CharUnits BaseOffset = Base.getBaseOffset() + RelativeBaseOffset; + + CharUnits BaseOffsetInLayoutClass = + OffsetInLayoutClass + RelativeBaseOffset; + + // Don't emit a secondary vtable for a primary base. We might however want + // to emit secondary vtables for other bases of this base. + if (BaseDecl == PrimaryBase) { + LayoutSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset), + BaseIsMorallyVirtual, BaseOffsetInLayoutClass); + continue; + } + + // Layout the primary vtable (and any secondary vtables) for this base. + LayoutPrimaryAndSecondaryVTables( + BaseSubobject(BaseDecl, BaseOffset), + BaseIsMorallyVirtual, + /*BaseIsVirtualInLayoutClass=*/false, + BaseOffsetInLayoutClass); + } +} + +void +VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, + CharUnits OffsetInLayoutClass, + VisitedVirtualBasesSetTy &VBases) { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + // Check if this base has a primary base. + if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) { + + // Check if it's virtual. + if (Layout.isPrimaryBaseVirtual()) { + bool IsPrimaryVirtualBase = true; + + if (isBuildingConstructorVTable()) { + // Check if the base is actually a primary base in the class we use for + // layout. + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + CharUnits PrimaryBaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(PrimaryBase); + + // We know that the base is not a primary base in the layout class if + // the base offsets are different. + if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass) + IsPrimaryVirtualBase = false; + } + + if (IsPrimaryVirtualBase) + PrimaryVirtualBases.insert(PrimaryBase); + } + } + + // Traverse bases, looking for more primary virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + CharUnits BaseOffsetInLayoutClass; + + if (I->isVirtual()) { + if (!VBases.insert(BaseDecl)) + continue; + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + BaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(BaseDecl); + } else { + BaseOffsetInLayoutClass = + OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl); + } + + DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases); + } +} + +void +VTableBuilder::LayoutVTablesForVirtualBases(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases) { + // Itanium C++ ABI 2.5.2: + // Then come the virtual base virtual tables, also in inheritance graph + // order, and again excluding primary bases (which share virtual tables with + // the classes for which they are primary). + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Check if this base needs a vtable. (If it's virtual, not a primary base + // of some other class, and we haven't visited it before). + if (I->isVirtual() && BaseDecl->isDynamicClass() && + !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) { + const ASTRecordLayout &MostDerivedClassLayout = + Context.getASTRecordLayout(MostDerivedClass); + CharUnits BaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + CharUnits BaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(BaseDecl); + + LayoutPrimaryAndSecondaryVTables( + BaseSubobject(BaseDecl, BaseOffset), + /*BaseIsMorallyVirtual=*/true, + /*BaseIsVirtualInLayoutClass=*/true, + BaseOffsetInLayoutClass); + } + + // We only need to check the base for virtual base vtables if it actually + // has virtual bases. + if (BaseDecl->getNumVBases()) + LayoutVTablesForVirtualBases(BaseDecl, VBases); + } +} + +/// dumpLayout - Dump the vtable layout. +void VTableBuilder::dumpLayout(raw_ostream& Out) { + + if (isBuildingConstructorVTable()) { + Out << "Construction vtable for ('"; + Out << MostDerivedClass->getQualifiedNameAsString() << "', "; + Out << MostDerivedClassOffset.getQuantity() << ") in '"; + Out << LayoutClass->getQualifiedNameAsString(); + } else { + Out << "Vtable for '"; + Out << MostDerivedClass->getQualifiedNameAsString(); + } + Out << "' (" << Components.size() << " entries).\n"; + + // Iterate through the address points and insert them into a new map where + // they are keyed by the index and not the base object. + // Since an address point can be shared by multiple subobjects, we use an + // STL multimap. + std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex; + for (AddressPointsMapTy::const_iterator I = AddressPoints.begin(), + E = AddressPoints.end(); I != E; ++I) { + const BaseSubobject& Base = I->first; + uint64_t Index = I->second; + + AddressPointsByIndex.insert(std::make_pair(Index, Base)); + } + + for (unsigned I = 0, E = Components.size(); I != E; ++I) { + uint64_t Index = I; + + Out << llvm::format("%4d | ", I); + + const VTableComponent &Component = Components[I]; + + // Dump the component. + switch (Component.getKind()) { + + case VTableComponent::CK_VCallOffset: + Out << "vcall_offset (" + << Component.getVCallOffset().getQuantity() + << ")"; + break; + + case VTableComponent::CK_VBaseOffset: + Out << "vbase_offset (" + << Component.getVBaseOffset().getQuantity() + << ")"; + break; + + case VTableComponent::CK_OffsetToTop: + Out << "offset_to_top (" + << Component.getOffsetToTop().getQuantity() + << ")"; + break; + + case VTableComponent::CK_RTTI: + Out << Component.getRTTIDecl()->getQualifiedNameAsString() << " RTTI"; + break; + + case VTableComponent::CK_FunctionPointer: { + const CXXMethodDecl *MD = Component.getFunctionDecl(); + + std::string Str = + PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, + MD); + Out << Str; + if (MD->isPure()) + Out << " [pure]"; + + ThunkInfo Thunk = VTableThunks.lookup(I); + if (!Thunk.isEmpty()) { + // If this function pointer has a return adjustment, dump it. + if (!Thunk.Return.isEmpty()) { + Out << "\n [return adjustment: "; + Out << Thunk.Return.NonVirtual << " non-virtual"; + + if (Thunk.Return.VBaseOffsetOffset) { + Out << ", " << Thunk.Return.VBaseOffsetOffset; + Out << " vbase offset offset"; + } + + Out << ']'; + } + + // If this function pointer has a 'this' pointer adjustment, dump it. + if (!Thunk.This.isEmpty()) { + Out << "\n [this adjustment: "; + Out << Thunk.This.NonVirtual << " non-virtual"; + + if (Thunk.This.VCallOffsetOffset) { + Out << ", " << Thunk.This.VCallOffsetOffset; + Out << " vcall offset offset"; + } + + Out << ']'; + } + } + + break; + } + + case VTableComponent::CK_CompleteDtorPointer: + case VTableComponent::CK_DeletingDtorPointer: { + bool IsComplete = + Component.getKind() == VTableComponent::CK_CompleteDtorPointer; + + const CXXDestructorDecl *DD = Component.getDestructorDecl(); + + Out << DD->getQualifiedNameAsString(); + if (IsComplete) + Out << "() [complete]"; + else + Out << "() [deleting]"; + + if (DD->isPure()) + Out << " [pure]"; + + ThunkInfo Thunk = VTableThunks.lookup(I); + if (!Thunk.isEmpty()) { + // If this destructor has a 'this' pointer adjustment, dump it. + if (!Thunk.This.isEmpty()) { + Out << "\n [this adjustment: "; + Out << Thunk.This.NonVirtual << " non-virtual"; + + if (Thunk.This.VCallOffsetOffset) { + Out << ", " << Thunk.This.VCallOffsetOffset; + Out << " vcall offset offset"; + } + + Out << ']'; + } + } + + break; + } + + case VTableComponent::CK_UnusedFunctionPointer: { + const CXXMethodDecl *MD = Component.getUnusedFunctionDecl(); + + std::string Str = + PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, + MD); + Out << "[unused] " << Str; + if (MD->isPure()) + Out << " [pure]"; + } + + } + + Out << '\n'; + + // Dump the next address point. + uint64_t NextIndex = Index + 1; + if (AddressPointsByIndex.count(NextIndex)) { + if (AddressPointsByIndex.count(NextIndex) == 1) { + const BaseSubobject &Base = + AddressPointsByIndex.find(NextIndex)->second; + + Out << " -- (" << Base.getBase()->getQualifiedNameAsString(); + Out << ", " << Base.getBaseOffset().getQuantity(); + Out << ") vtable address --\n"; + } else { + CharUnits BaseOffset = + AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset(); + + // We store the class names in a set to get a stable order. + std::set<std::string> ClassNames; + for (std::multimap<uint64_t, BaseSubobject>::const_iterator I = + AddressPointsByIndex.lower_bound(NextIndex), E = + AddressPointsByIndex.upper_bound(NextIndex); I != E; ++I) { + assert(I->second.getBaseOffset() == BaseOffset && + "Invalid base offset!"); + const CXXRecordDecl *RD = I->second.getBase(); + ClassNames.insert(RD->getQualifiedNameAsString()); + } + + for (std::set<std::string>::const_iterator I = ClassNames.begin(), + E = ClassNames.end(); I != E; ++I) { + Out << " -- (" << *I; + Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n"; + } + } + } + } + + Out << '\n'; + + if (isBuildingConstructorVTable()) + return; + + if (MostDerivedClass->getNumVBases()) { + // We store the virtual base class names and their offsets in a map to get + // a stable order. + + std::map<std::string, CharUnits> ClassNamesAndOffsets; + for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(), + E = VBaseOffsetOffsets.end(); I != E; ++I) { + std::string ClassName = I->first->getQualifiedNameAsString(); + CharUnits OffsetOffset = I->second; + ClassNamesAndOffsets.insert( + std::make_pair(ClassName, OffsetOffset)); + } + + Out << "Virtual base offset offsets for '"; + Out << MostDerivedClass->getQualifiedNameAsString() << "' ("; + Out << ClassNamesAndOffsets.size(); + Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n"; + + for (std::map<std::string, CharUnits>::const_iterator I = + ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end(); + I != E; ++I) + Out << " " << I->first << " | " << I->second.getQuantity() << '\n'; + + Out << "\n"; + } + + if (!Thunks.empty()) { + // We store the method names in a map to get a stable order. + std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls; + + for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end(); + I != E; ++I) { + const CXXMethodDecl *MD = I->first; + std::string MethodName = + PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, + MD); + + MethodNamesAndDecls.insert(std::make_pair(MethodName, MD)); + } + + for (std::map<std::string, const CXXMethodDecl *>::const_iterator I = + MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end(); + I != E; ++I) { + const std::string &MethodName = I->first; + const CXXMethodDecl *MD = I->second; + + ThunkInfoVectorTy ThunksVector = Thunks[MD]; + std::sort(ThunksVector.begin(), ThunksVector.end()); + + Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size(); + Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n"; + + for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) { + const ThunkInfo &Thunk = ThunksVector[I]; + + Out << llvm::format("%4d | ", I); + + // If this function pointer has a return pointer adjustment, dump it. + if (!Thunk.Return.isEmpty()) { + Out << "return adjustment: " << Thunk.This.NonVirtual; + Out << " non-virtual"; + if (Thunk.Return.VBaseOffsetOffset) { + Out << ", " << Thunk.Return.VBaseOffsetOffset; + Out << " vbase offset offset"; + } + + if (!Thunk.This.isEmpty()) + Out << "\n "; + } + + // If this function pointer has a 'this' pointer adjustment, dump it. + if (!Thunk.This.isEmpty()) { + Out << "this adjustment: "; + Out << Thunk.This.NonVirtual << " non-virtual"; + + if (Thunk.This.VCallOffsetOffset) { + Out << ", " << Thunk.This.VCallOffsetOffset; + Out << " vcall offset offset"; + } + } + + Out << '\n'; + } + + Out << '\n'; + } + } + + // Compute the vtable indices for all the member functions. + // Store them in a map keyed by the index so we'll get a sorted table. + std::map<uint64_t, std::string> IndicesMap; + + for (CXXRecordDecl::method_iterator i = MostDerivedClass->method_begin(), + e = MostDerivedClass->method_end(); i != e; ++i) { + const CXXMethodDecl *MD = *i; + + // We only want virtual member functions. + if (!MD->isVirtual()) + continue; + + std::string MethodName = + PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, + MD); + + if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { + IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))] = + MethodName + " [complete]"; + IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] = + MethodName + " [deleting]"; + } else { + IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName; + } + } + + // Print the vtable indices for all the member functions. + if (!IndicesMap.empty()) { + Out << "VTable indices for '"; + Out << MostDerivedClass->getQualifiedNameAsString(); + Out << "' (" << IndicesMap.size() << " entries).\n"; + + for (std::map<uint64_t, std::string>::const_iterator I = IndicesMap.begin(), + E = IndicesMap.end(); I != E; ++I) { + uint64_t VTableIndex = I->first; + const std::string &MethodName = I->second; + + Out << llvm::format(" %4u | ", VTableIndex) << MethodName << '\n'; + } + } + + Out << '\n'; +} + +} + +VTableLayout::VTableLayout(uint64_t NumVTableComponents, + const VTableComponent *VTableComponents, + uint64_t NumVTableThunks, + const VTableThunkTy *VTableThunks, + const AddressPointsMapTy &AddressPoints) + : NumVTableComponents(NumVTableComponents), + VTableComponents(new VTableComponent[NumVTableComponents]), + NumVTableThunks(NumVTableThunks), + VTableThunks(new VTableThunkTy[NumVTableThunks]), + AddressPoints(AddressPoints) { + std::copy(VTableComponents, VTableComponents+NumVTableComponents, + this->VTableComponents); + std::copy(VTableThunks, VTableThunks+NumVTableThunks, this->VTableThunks); +} + +VTableLayout::~VTableLayout() { + delete[] VTableComponents; +} + +VTableContext::~VTableContext() { + llvm::DeleteContainerSeconds(VTableLayouts); +} + +static void +CollectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, + VTableBuilder::PrimaryBasesSetVectorTy &PrimaryBases) { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + + if (!PrimaryBase) + return; + + CollectPrimaryBases(PrimaryBase, Context, PrimaryBases); + + if (!PrimaryBases.insert(PrimaryBase)) + llvm_unreachable("Found a duplicate primary base!"); +} + +void VTableContext::ComputeMethodVTableIndices(const CXXRecordDecl *RD) { + + // Itanium C++ ABI 2.5.2: + // The order of the virtual function pointers in a virtual table is the + // order of declaration of the corresponding member functions in the class. + // + // There is an entry for any virtual function declared in a class, + // whether it is a new function or overrides a base class function, + // unless it overrides a function from the primary base, and conversion + // between their return types does not require an adjustment. + + int64_t CurrentIndex = 0; + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + + if (PrimaryBase) { + assert(PrimaryBase->isCompleteDefinition() && + "Should have the definition decl of the primary base!"); + + // Since the record decl shares its vtable pointer with the primary base + // we need to start counting at the end of the primary base's vtable. + CurrentIndex = getNumVirtualFunctionPointers(PrimaryBase); + } + + // Collect all the primary bases, so we can check whether methods override + // a method from the base. + VTableBuilder::PrimaryBasesSetVectorTy PrimaryBases; + CollectPrimaryBases(RD, Context, PrimaryBases); + + const CXXDestructorDecl *ImplicitVirtualDtor = 0; + + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); i != e; ++i) { + const CXXMethodDecl *MD = *i; + + // We only want virtual methods. + if (!MD->isVirtual()) + continue; + + // Check if this method overrides a method in the primary base. + if (const CXXMethodDecl *OverriddenMD = + FindNearestOverriddenMethod(MD, PrimaryBases)) { + // Check if converting from the return type of the method to the + // return type of the overridden method requires conversion. + if (ComputeReturnAdjustmentBaseOffset(Context, MD, + OverriddenMD).isEmpty()) { + // This index is shared between the index in the vtable of the primary + // base class. + if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { + const CXXDestructorDecl *OverriddenDD = + cast<CXXDestructorDecl>(OverriddenMD); + + // Add both the complete and deleting entries. + MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = + getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete)); + MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = + getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting)); + } else { + MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD); + } + + // We don't need to add an entry for this method. + continue; + } + } + + if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { + if (MD->isImplicit()) { + assert(!ImplicitVirtualDtor && + "Did already see an implicit virtual dtor!"); + ImplicitVirtualDtor = DD; + continue; + } + + // Add the complete dtor. + MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++; + + // Add the deleting dtor. + MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++; + } else { + // Add the entry. + MethodVTableIndices[MD] = CurrentIndex++; + } + } + + if (ImplicitVirtualDtor) { + // Itanium C++ ABI 2.5.2: + // If a class has an implicitly-defined virtual destructor, + // its entries come after the declared virtual function pointers. + + // Add the complete dtor. + MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] = + CurrentIndex++; + + // Add the deleting dtor. + MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Deleting)] = + CurrentIndex++; + } + + NumVirtualFunctionPointers[RD] = CurrentIndex; +} + +uint64_t VTableContext::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) { + llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I = + NumVirtualFunctionPointers.find(RD); + if (I != NumVirtualFunctionPointers.end()) + return I->second; + + ComputeMethodVTableIndices(RD); + + I = NumVirtualFunctionPointers.find(RD); + assert(I != NumVirtualFunctionPointers.end() && "Did not find entry!"); + return I->second; +} + +uint64_t VTableContext::getMethodVTableIndex(GlobalDecl GD) { + MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD); + if (I != MethodVTableIndices.end()) + return I->second; + + const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent(); + + ComputeMethodVTableIndices(RD); + + I = MethodVTableIndices.find(GD); + assert(I != MethodVTableIndices.end() && "Did not find index!"); + return I->second; +} + +CharUnits +VTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, + const CXXRecordDecl *VBase) { + ClassPairTy ClassPair(RD, VBase); + + VirtualBaseClassOffsetOffsetsMapTy::iterator I = + VirtualBaseClassOffsetOffsets.find(ClassPair); + if (I != VirtualBaseClassOffsetOffsets.end()) + return I->second; + + VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/0, + BaseSubobject(RD, CharUnits::Zero()), + /*BaseIsVirtual=*/false, + /*OffsetInLayoutClass=*/CharUnits::Zero()); + + for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I = + Builder.getVBaseOffsetOffsets().begin(), + E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) { + // Insert all types. + ClassPairTy ClassPair(RD, I->first); + + VirtualBaseClassOffsetOffsets.insert( + std::make_pair(ClassPair, I->second)); + } + + I = VirtualBaseClassOffsetOffsets.find(ClassPair); + assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!"); + + return I->second; +} + +static VTableLayout *CreateVTableLayout(const VTableBuilder &Builder) { + SmallVector<VTableLayout::VTableThunkTy, 1> + VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); + std::sort(VTableThunks.begin(), VTableThunks.end()); + + return new VTableLayout(Builder.getNumVTableComponents(), + Builder.vtable_component_begin(), + VTableThunks.size(), + VTableThunks.data(), + Builder.getAddressPoints()); +} + +void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { + const VTableLayout *&Entry = VTableLayouts[RD]; + + // Check if we've computed this information before. + if (Entry) + return; + + VTableBuilder Builder(*this, RD, CharUnits::Zero(), + /*MostDerivedClassIsVirtual=*/0, RD); + Entry = CreateVTableLayout(Builder); + + // Add the known thunks. + Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); + + // If we don't have the vbase information for this class, insert it. + // getVirtualBaseOffsetOffset will compute it separately without computing + // the rest of the vtable related information. + if (!RD->getNumVBases()) + return; + + const RecordType *VBaseRT = + RD->vbases_begin()->getType()->getAs<RecordType>(); + const CXXRecordDecl *VBase = cast<CXXRecordDecl>(VBaseRT->getDecl()); + + if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase))) + return; + + for (VTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator I = + Builder.getVBaseOffsetOffsets().begin(), + E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) { + // Insert all types. + ClassPairTy ClassPair(RD, I->first); + + VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second)); + } +} + +VTableLayout *VTableContext::createConstructionVTableLayout( + const CXXRecordDecl *MostDerivedClass, + CharUnits MostDerivedClassOffset, + bool MostDerivedClassIsVirtual, + const CXXRecordDecl *LayoutClass) { + VTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset, + MostDerivedClassIsVirtual, LayoutClass); + return CreateVTableLayout(Builder); +} |