diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
37 files changed, 3574 insertions, 1791 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index 0fa0216..91f1e20 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -573,7 +573,7 @@ bool APValue::hasLValuePath() const { ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { assert(isLValue() && hasLValuePath() && "Invalid accessor"); const LV &LVal = *((const LV*)(const char*)Data.buffer); - return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength); + return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength); } unsigned APValue::getLValueCallIndex() const { @@ -623,7 +623,7 @@ ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { assert(isMemberPointer() && "Invalid accessor"); const MemberPointerData &MPD = *((const MemberPointerData *)(const char *)Data.buffer); - return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength); + return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength); } void APValue::MakeLValue() { diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index bccdae9..6b864d0 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -699,9 +699,10 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, 1, // opencl_global 2, // opencl_local 3, // opencl_constant - 4, // cuda_device - 5, // cuda_constant - 6 // cuda_shared + 4, // opencl_generic + 5, // cuda_device + 6, // cuda_constant + 7 // cuda_shared }; return &FakeAddrSpaceMap; } else { @@ -722,35 +723,28 @@ static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI, llvm_unreachable("getAddressSpaceMapMangling() doesn't cover anything."); } -ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, +ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins) - : FunctionProtoTypes(this_()), - TemplateSpecializationTypes(this_()), - DependentTemplateSpecializationTypes(this_()), - SubstTemplateTemplateParmPacks(this_()), - GlobalNestedNameSpecifier(nullptr), - Int128Decl(nullptr), UInt128Decl(nullptr), Float128StubDecl(nullptr), - BuiltinVaListDecl(nullptr), - ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr), - ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr), - CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr), - FILEDecl(nullptr), - jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr), - BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr), - cudaConfigureCallDecl(nullptr), - NullTypeSourceInfo(QualType()), - FirstLocalImport(), LastLocalImport(), - SourceMgr(SM), LangOpts(LOpts), - AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts), - Idents(idents), Selectors(sels), - BuiltinInfo(builtins), - DeclarationNames(*this), - ExternalSource(nullptr), Listener(nullptr), - Comments(SM), CommentsLoaded(false), - CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), - LastSDM(nullptr, 0) -{ + : FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()), + DependentTemplateSpecializationTypes(this_()), + SubstTemplateTemplateParmPacks(this_()), + GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr), + UInt128Decl(nullptr), Float128StubDecl(nullptr), + BuiltinVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), + ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr), + CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr), + FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr), + ucontext_tDecl(nullptr), BlockDescriptorType(nullptr), + BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr), + FirstLocalImport(), LastLocalImport(), + SourceMgr(SM), LangOpts(LOpts), + SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFile, SM)), + AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts), + Idents(idents), Selectors(sels), BuiltinInfo(builtins), + DeclarationNames(*this), ExternalSource(nullptr), Listener(nullptr), + Comments(SM), CommentsLoaded(false), + CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) { TUDecl = TranslationUnitDecl::Create(*this); } @@ -1413,9 +1407,9 @@ std::pair<CharUnits, CharUnits> ASTContext::getTypeInfoInChars(const Type *T) const { if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) return getConstantArrayInfoInChars(*this, CAT); - std::pair<uint64_t, unsigned> Info = getTypeInfo(T); - return std::make_pair(toCharUnitsFromBits(Info.first), - toCharUnitsFromBits(Info.second)); + TypeInfo Info = getTypeInfo(T); + return std::make_pair(toCharUnitsFromBits(Info.Width), + toCharUnitsFromBits(Info.Align)); } std::pair<CharUnits, CharUnits> @@ -1423,14 +1417,23 @@ ASTContext::getTypeInfoInChars(QualType T) const { return getTypeInfoInChars(T.getTypePtr()); } -std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const { - TypeInfoMap::iterator it = MemoizedTypeInfo.find(T); - if (it != MemoizedTypeInfo.end()) - return it->second; +bool ASTContext::isAlignmentRequired(const Type *T) const { + return getTypeInfo(T).AlignIsRequired; +} + +bool ASTContext::isAlignmentRequired(QualType T) const { + return isAlignmentRequired(T.getTypePtr()); +} + +TypeInfo ASTContext::getTypeInfo(const Type *T) const { + TypeInfoMap::iterator I = MemoizedTypeInfo.find(T); + if (I != MemoizedTypeInfo.end()) + return I->second; - std::pair<uint64_t, unsigned> Info = getTypeInfoImpl(T); - MemoizedTypeInfo.insert(std::make_pair(T, Info)); - return Info; + // This call can invalidate MemoizedTypeInfo[T], so we need a second lookup. + TypeInfo TI = getTypeInfoImpl(T); + MemoizedTypeInfo[T] = TI; + return TI; } /// getTypeInfoImpl - Return the size of the specified type, in bits. This @@ -1439,10 +1442,10 @@ std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const { /// FIXME: Pointers into different addr spaces could have different sizes and /// alignment requirements: getPointerInfo should take an AddrSpace, this /// should take a QualType, &c. -std::pair<uint64_t, unsigned> -ASTContext::getTypeInfoImpl(const Type *T) const { - uint64_t Width=0; - unsigned Align=8; +TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { + uint64_t Width = 0; + unsigned Align = 8; + bool AlignIsRequired = false; switch (T->getTypeClass()) { #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) @@ -1471,12 +1474,12 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::ConstantArray: { const ConstantArrayType *CAT = cast<ConstantArrayType>(T); - std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType()); + TypeInfo EltInfo = getTypeInfo(CAT->getElementType()); uint64_t Size = CAT->getSize().getZExtValue(); - assert((Size == 0 || EltInfo.first <= (uint64_t)(-1)/Size) && + assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) && "Overflow in array type bit size evaluation"); - Width = EltInfo.first*Size; - Align = EltInfo.second; + Width = EltInfo.Width * Size; + Align = EltInfo.Align; if (!getTargetInfo().getCXXABI().isMicrosoft() || getTargetInfo().getPointerWidth(0) == 64) Width = llvm::RoundUpToAlignment(Width, Align); @@ -1485,8 +1488,8 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::ExtVector: case Type::Vector: { const VectorType *VT = cast<VectorType>(T); - std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType()); - Width = EltInfo.first*VT->getNumElements(); + TypeInfo EltInfo = getTypeInfo(VT->getElementType()); + Width = EltInfo.Width * VT->getNumElements(); Align = Width; // If the alignment is not a power of 2, round up to the next power of 2. // This happens for non-power-of-2 length vectors. @@ -1638,10 +1641,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Complex: { // Complex types have the same alignment as their elements, but twice the // size. - std::pair<uint64_t, unsigned> EltInfo = - getTypeInfo(cast<ComplexType>(T)->getElementType()); - Width = EltInfo.first*2; - Align = EltInfo.second; + TypeInfo EltInfo = getTypeInfo(cast<ComplexType>(T)->getElementType()); + Width = EltInfo.Width * 2; + Align = EltInfo.Align; break; } case Type::ObjCObject: @@ -1692,16 +1694,18 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Typedef: { const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl(); - std::pair<uint64_t, unsigned> Info - = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); + TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); // If the typedef has an aligned attribute on it, it overrides any computed // alignment we have. This violates the GCC documentation (which says that // attribute(aligned) can only round up) but matches its implementation. - if (unsigned AttrAlign = Typedef->getMaxAlignment()) + if (unsigned AttrAlign = Typedef->getMaxAlignment()) { Align = AttrAlign; - else - Align = Info.second; - Width = Info.first; + AlignIsRequired = true; + } else { + Align = Info.Align; + AlignIsRequired = Info.AlignIsRequired; + } + Width = Info.Width; break; } @@ -1714,10 +1718,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Atomic: { // Start with the base type information. - std::pair<uint64_t, unsigned> Info - = getTypeInfo(cast<AtomicType>(T)->getValueType()); - Width = Info.first; - Align = Info.second; + TypeInfo Info = getTypeInfo(cast<AtomicType>(T)->getValueType()); + Width = Info.Width; + Align = Info.Align; // If the size of the type doesn't exceed the platform's max // atomic promotion width, make the size and alignment more @@ -1735,7 +1738,7 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2"); - return std::make_pair(Width, Align); + return TypeInfo(Width, Align, AlignIsRequired); } /// toCharUnitsFromBits - Convert a size in bits to a size in characters. @@ -1771,13 +1774,12 @@ CharUnits ASTContext::getTypeAlignInChars(const Type *T) const { /// alignment in cases where it is beneficial for performance to overalign /// a data type. unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { - unsigned ABIAlign = getTypeAlign(T); + TypeInfo TI = getTypeInfo(T); + unsigned ABIAlign = TI.Align; if (Target->getTriple().getArch() == llvm::Triple::xcore) return ABIAlign; // Never overalign on XCore. - const TypedefType *TT = T->getAs<TypedefType>(); - // Double and long long should be naturally aligned if possible. T = T->getBaseElementTypeUnsafe(); if (const ComplexType *CT = T->getAs<ComplexType>()) @@ -1787,7 +1789,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { T->isSpecificBuiltinType(BuiltinType::ULongLong)) // Don't increase the alignment if an alignment attribute was specified on a // typedef declaration. - if (!TT || !TT->getDecl()->getMaxAlignment()) + if (!TI.AlignIsRequired) return std::max(ABIAlign, (unsigned)getTypeSize(T)); return ABIAlign; @@ -2110,6 +2112,62 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, L->DeducedReturnType(FD, ResultType); } +/// Get a function type and produce the equivalent function type with the +/// specified exception specification. Type sugar that can be present on a +/// declaration of a function with an exception specification is permitted +/// and preserved. Other type sugar (for instance, typedefs) is not. +static QualType getFunctionTypeWithExceptionSpec( + ASTContext &Context, QualType Orig, + const FunctionProtoType::ExceptionSpecInfo &ESI) { + // Might have some parens. + if (auto *PT = dyn_cast<ParenType>(Orig)) + return Context.getParenType( + getFunctionTypeWithExceptionSpec(Context, PT->getInnerType(), ESI)); + + // Might have a calling-convention attribute. + if (auto *AT = dyn_cast<AttributedType>(Orig)) + return Context.getAttributedType( + AT->getAttrKind(), + getFunctionTypeWithExceptionSpec(Context, AT->getModifiedType(), ESI), + getFunctionTypeWithExceptionSpec(Context, AT->getEquivalentType(), + ESI)); + + // Anything else must be a function type. Rebuild it with the new exception + // specification. + const FunctionProtoType *Proto = cast<FunctionProtoType>(Orig); + return Context.getFunctionType( + Proto->getReturnType(), Proto->getParamTypes(), + Proto->getExtProtoInfo().withExceptionSpec(ESI)); +} + +void ASTContext::adjustExceptionSpec( + FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI, + bool AsWritten) { + // Update the type. + QualType Updated = + getFunctionTypeWithExceptionSpec(*this, FD->getType(), ESI); + FD->setType(Updated); + + if (!AsWritten) + return; + + // Update the type in the type source information too. + if (TypeSourceInfo *TSInfo = FD->getTypeSourceInfo()) { + // If the type and the type-as-written differ, we may need to update + // the type-as-written too. + if (TSInfo->getType() != FD->getType()) + Updated = getFunctionTypeWithExceptionSpec(*this, TSInfo->getType(), ESI); + + // FIXME: When we get proper type location information for exceptions, + // we'll also have to rebuild the TypeSourceInfo. For now, we just patch + // up the TypeSourceInfo; + assert(TypeLoc::getFullDataSizeForType(Updated) == + TypeLoc::getFullDataSizeForType(TSInfo->getType()) && + "TypeLoc size mismatch from updating exception specification"); + TSInfo->overrideType(Updated); + } +} + /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. QualType ASTContext::getComplexType(QualType T) const { @@ -2840,7 +2898,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, // Determine whether the type being created is already canonical or not. bool isCanonical = - EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) && + EPI.ExceptionSpec.Type == EST_None && isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn; for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) @@ -2857,8 +2915,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; CanonicalEPI.HasTrailingReturn = false; - CanonicalEPI.ExceptionSpecType = EST_None; - CanonicalEPI.NumExceptions = 0; + CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); // Result types do not have ARC lifetime qualifiers. QualType CanResultTy = getCanonicalType(ResultTy); @@ -2886,13 +2943,13 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, // specification. size_t Size = sizeof(FunctionProtoType) + NumArgs * sizeof(QualType); - if (EPI.ExceptionSpecType == EST_Dynamic) { - Size += EPI.NumExceptions * sizeof(QualType); - } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + if (EPI.ExceptionSpec.Type == EST_Dynamic) { + Size += EPI.ExceptionSpec.Exceptions.size() * sizeof(QualType); + } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { Size += sizeof(Expr*); - } else if (EPI.ExceptionSpecType == EST_Uninstantiated) { + } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { Size += 2 * sizeof(FunctionDecl*); - } else if (EPI.ExceptionSpecType == EST_Unevaluated) { + } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { Size += sizeof(FunctionDecl*); } if (EPI.ConsumedParameters) @@ -4099,7 +4156,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { case TemplateArgument::Declaration: { ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl()); - return TemplateArgument(D, Arg.isDeclForReferenceParam()); + return TemplateArgument(D, Arg.getParamTypeForDecl()); } case TemplateArgument::NullPtr: @@ -4188,7 +4245,8 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { } case NestedNameSpecifier::Global: - // The global specifier is canonical and unique. + case NestedNameSpecifier::Super: + // The global specifier and __super specifer are canonical and unique. return NNS; } @@ -4414,7 +4472,11 @@ unsigned ASTContext::getIntegerRank(const Type *T) const { QualType ASTContext::isPromotableBitField(Expr *E) const { if (E->isTypeDependent() || E->isValueDependent()) return QualType(); - + + // FIXME: We should not do this unless E->refersToBitField() is true. This + // matters in C where getSourceBitField() will find bit-fields for various + // cases where the source expression is not a bit-field designator. + FieldDecl *Field = E->getSourceBitField(); // FIXME: conditional bit-fields? if (!Field) return QualType(); @@ -4423,9 +4485,20 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { 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. - // For instance, unsigned long bf : 4 gets promoted to signed int. + // C++ [conv.prom]p5: + // A prvalue for an integral bit-field can be converted to a prvalue of type + // int if int can represent all the values of the bit-field; otherwise, it + // can be converted to unsigned int if unsigned int can represent all the + // values of the bit-field. If the bit-field is larger yet, no integral + // promotion applies to it. + // C11 6.3.1.1/2: + // [For a bit-field of type _Bool, int, signed int, or unsigned int:] + // If an int can represent all values of the original type (as restricted by + // the width, for a bit-field), the value is converted to an int; otherwise, + // it is converted to an unsigned int. + // + // FIXME: C does not permit promotion of a 'long : 3' bitfield to int. + // We perform that promotion here to match GCC and C++. if (BitWidth < IntSize) return IntTy; @@ -4433,9 +4506,10 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { return FT->isSignedIntegerType() ? IntTy : UnsignedIntTy; // Types bigger than int are not subject to promotions, and therefore act - // like the base type. - // FIXME: This doesn't quite match what gcc does, but what gcc does here - // is ridiculous. + // like the base type. GCC has some weird bugs in this area that we + // deliberately do not follow (GCC follows a pre-standard resolution to + // C's DR315 which treats bit-width as being part of the type, and this leaks + // into their semantics in some cases). return QualType(); } @@ -5090,13 +5164,15 @@ void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const { } void ASTContext::getObjCEncodingForType(QualType T, std::string& S, - const FieldDecl *Field) const { + const FieldDecl *Field, + QualType *NotEncodedT) const { // We follow the behavior of gcc, expanding structures which are // directly pointed to, and expanding embedded structures. Note that // these rules are sufficient to prevent recursive encoding of the // same type. getObjCEncodingForTypeImpl(T, S, true, true, Field, - true /* outermost type */); + true /* outermost type */, false, false, + false, false, false, NotEncodedT); } void ASTContext::getObjCEncodingForPropertyType(QualType T, @@ -5222,7 +5298,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, bool StructField, bool EncodeBlockParameters, bool EncodeClassNames, - bool EncodePointerToObjCTypedef) const { + bool EncodePointerToObjCTypedef, + QualType *NotEncodedT) const { CanQualType CT = getCanonicalType(T); switch (CT->getTypeClass()) { case Type::Builtin: @@ -5238,16 +5315,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::Complex: { const ComplexType *CT = T->castAs<ComplexType>(); S += 'j'; - getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr, - false, false); + getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr); return; } case Type::Atomic: { const AtomicType *AT = T->castAs<AtomicType>(); S += 'A'; - getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr, - false, false); + getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr); return; } @@ -5318,7 +5393,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, getLegacyIntegralTypeEncoding(PointeeTy); getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, - nullptr); + nullptr, false, false, false, false, false, false, + NotEncodedT); return; } @@ -5346,7 +5422,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } getObjCEncodingForTypeImpl(AT->getElementType(), S, - false, ExpandStructures, FD); + false, ExpandStructures, FD, + false, false, false, false, false, false, + NotEncodedT); S += ']'; } return; @@ -5378,7 +5456,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (ExpandStructures) { S += '='; if (!RDecl->isUnion()) { - getObjCEncodingForStructureImpl(RDecl, S, FD); + getObjCEncodingForStructureImpl(RDecl, S, FD, true, NotEncodedT); } else { for (const auto *Field : RDecl->fields()) { if (FD) { @@ -5397,7 +5475,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, getObjCEncodingForTypeImpl(qt, S, false, true, FD, /*OutermostType*/false, /*EncodingProperty*/false, - /*StructField*/true); + /*StructField*/true, + false, false, false, NotEncodedT); } } } @@ -5417,7 +5496,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, getObjCEncodingForTypeImpl( FT->getReturnType(), S, ExpandPointedToStructures, ExpandStructures, FD, false /* OutermostType */, EncodingProperty, - false /* StructField */, EncodeBlockParameters, EncodeClassNames); + false /* StructField */, EncodeBlockParameters, EncodeClassNames, false, + NotEncodedT); // Block self S += "@?"; // Block parameters @@ -5426,7 +5506,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, getObjCEncodingForTypeImpl( I, S, ExpandPointedToStructures, ExpandStructures, FD, false /* OutermostType */, EncodingProperty, - false /* StructField */, EncodeBlockParameters, EncodeClassNames); + false /* StructField */, EncodeBlockParameters, EncodeClassNames, + false, NotEncodedT); } S += '>'; } @@ -5468,7 +5549,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, else getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, false, false, false, false, false, - EncodePointerToObjCTypedef); + EncodePointerToObjCTypedef, + NotEncodedT); } S += '}'; return; @@ -5555,19 +5637,21 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // gcc just blithely ignores member pointers. // FIXME: we shoul do better than that. 'M' is available. case Type::MemberPointer: - return; - + // This matches gcc's encoding, even though technically it is insufficient. + //FIXME. We should do a better job than gcc. case Type::Vector: case Type::ExtVector: - // This matches gcc's encoding, even though technically it is - // insufficient. - // FIXME. We should do a better job than gcc. - return; - + // Until we have a coherent encoding of these three types, issue warning. + { if (NotEncodedT) + *NotEncodedT = T; + return; + } + + // We could see an undeduced auto type here during error recovery. + // Just ignore it. case Type::Auto: - // We could see an undeduced auto type here during error recovery. - // Just ignore it. return; + #define ABSTRACT_TYPE(KIND, BASE) #define TYPE(KIND, BASE) @@ -5586,7 +5670,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, std::string &S, const FieldDecl *FD, - bool includeVBases) const { + bool includeVBases, + QualType *NotEncodedT) const { assert(RDecl && "Expected non-null RecordDecl"); assert(!RDecl->isUnion() && "Should not be called for unions"); if (!RDecl->getDefinition()) @@ -5610,12 +5695,11 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, } unsigned i = 0; - for (RecordDecl::field_iterator Field = RDecl->field_begin(), - FieldEnd = RDecl->field_end(); - Field != FieldEnd; ++Field, ++i) { + for (auto *Field : RDecl->fields()) { uint64_t offs = layout.getFieldOffset(i); FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), - std::make_pair(offs, *Field)); + std::make_pair(offs, Field)); + ++i; } if (CXXRec && includeVBases) { @@ -5691,7 +5775,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, // in the initial structure. Note that this differs from gcc which // expands virtual bases each time one is encountered in the hierarchy, // making the encoding type bigger than it really is. - getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false); + getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false, + NotEncodedT); assert(!base->isEmpty()); #ifndef NDEBUG CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize()); @@ -5715,7 +5800,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, getObjCEncodingForTypeImpl(qt, S, false, true, FD, /*OutermostType*/false, /*EncodingProperty*/false, - /*StructField*/true); + /*StructField*/true, + false, false, false, NotEncodedT); #ifndef NDEBUG CurOffs += getTypeSize(field->getType()); #endif @@ -6654,11 +6740,9 @@ void getIntersectionOfProtocols(ASTContext &Context, llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols; Context.CollectInheritedProtocols(RHS->getInterface(), RHSInheritedProtocols); - for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I = - RHSInheritedProtocols.begin(), - E = RHSInheritedProtocols.end(); I != E; ++I) - if (InheritedProtocolSet.count((*I))) - IntersectionOfProtocols.push_back((*I)); + for (ObjCProtocolDecl *ProtDecl : RHSInheritedProtocols) + if (InheritedProtocolSet.count(ProtDecl)) + IntersectionOfProtocols.push_back(ProtDecl); } } @@ -6708,58 +6792,40 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, if (LHS->getNumProtocols() == 0) return true; - // Okay, we know the LHS has protocol qualifiers. If the RHS doesn't, - // more detailed analysis is required. - if (RHS->getNumProtocols() == 0) { - // OK, if LHS is a superclass of RHS *and* - // this superclass is assignment compatible with LHS. - // false otherwise. - bool IsSuperClass = - LHS->getInterface()->isSuperClassOf(RHS->getInterface()); - if (IsSuperClass) { - // OK if conversion of LHS to SuperClass results in narrowing of types - // ; i.e., SuperClass may implement at least one of the protocols - // in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok. - // But not SuperObj<P1,P2,P3> = lhs<P1,P2>. - llvm::SmallPtrSet<ObjCProtocolDecl *, 8> SuperClassInheritedProtocols; - CollectInheritedProtocols(RHS->getInterface(), SuperClassInheritedProtocols); - // If super class has no protocols, it is not a match. - if (SuperClassInheritedProtocols.empty()) - return false; + // Okay, we know the LHS has protocol qualifiers. But RHS may or may not. + // More detailed analysis is required. + // OK, if LHS is same or a superclass of RHS *and* + // this LHS, or as RHS's super class is assignment compatible with LHS. + bool IsSuperClass = + LHS->getInterface()->isSuperClassOf(RHS->getInterface()); + if (IsSuperClass) { + // OK if conversion of LHS to SuperClass results in narrowing of types + // ; i.e., SuperClass may implement at least one of the protocols + // in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok. + // But not SuperObj<P1,P2,P3> = lhs<P1,P2>. + llvm::SmallPtrSet<ObjCProtocolDecl *, 8> SuperClassInheritedProtocols; + CollectInheritedProtocols(RHS->getInterface(), SuperClassInheritedProtocols); + // Also, if RHS has explicit quelifiers, include them for comparing with LHS's + // qualifiers. + for (auto *RHSPI : RHS->quals()) + SuperClassInheritedProtocols.insert(RHSPI->getCanonicalDecl()); + // If there is no protocols associated with RHS, it is not a match. + if (SuperClassInheritedProtocols.empty()) + return false; - for (const auto *LHSProto : LHS->quals()) { - bool SuperImplementsProtocol = false; - for (auto *SuperClassProto : SuperClassInheritedProtocols) { - if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) { - SuperImplementsProtocol = true; - break; - } + for (const auto *LHSProto : LHS->quals()) { + bool SuperImplementsProtocol = false; + for (auto *SuperClassProto : SuperClassInheritedProtocols) + if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) { + SuperImplementsProtocol = true; + break; } - if (!SuperImplementsProtocol) - return false; - } - return true; - } - return false; - } - - for (const auto *LHSPI : LHS->quals()) { - bool RHSImplementsProtocol = false; - - // If the RHS doesn't implement the protocol on the left, the types - // are incompatible. - for (auto *RHSPI : RHS->quals()) { - if (RHSPI->lookupProtocolNamed(LHSPI->getIdentifier())) { - RHSImplementsProtocol = true; - break; - } + if (!SuperImplementsProtocol) + return false; } - // FIXME: For better diagnostics, consider passing back the protocol name. - if (!RHSImplementsProtocol) - return false; + return true; } - // The RHS implements all protocols listed on the LHS. - return true; + return false; } bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) { @@ -7895,7 +7961,9 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // We never need to emit an uninstantiated function template. if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) return false; - } else + } else if (isa<OMPThreadPrivateDecl>(D)) + return true; + else return false; // If this is a member of a class template, we do not need to emit it. @@ -8236,7 +8304,7 @@ namespace { } // end namespace -ASTContext::ParentVector +ArrayRef<ast_type_traits::DynTypedNode> ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { assert(Node.getMemoizationData() && "Invariant broken: only nodes that support memoization may be " @@ -8249,13 +8317,12 @@ ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { } ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData()); if (I == AllParents->end()) { - return ParentVector(); + return None; } - if (I->second.is<ast_type_traits::DynTypedNode *>()) { - return ParentVector(1, *I->second.get<ast_type_traits::DynTypedNode *>()); + if (auto *N = I->second.dyn_cast<ast_type_traits::DynTypedNode *>()) { + return llvm::makeArrayRef(N, 1); } - const auto &Parents = *I->second.get<ParentVector *>(); - return ParentVector(Parents.begin(), Parents.end()); + return *I->second.get<ParentVector *>(); } bool diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 8c8b1df..3212359 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -342,26 +342,22 @@ void clang::FormatASTNodeDiagnosticArgument( assert(DC && "Should never have a null declaration context"); NeedQuotes = false; + // FIXME: Get the strings for DeclContext from some localized place if (DC->isTranslationUnit()) { - // FIXME: Get these strings from some localized place if (Context.getLangOpts().CPlusPlus) OS << "the global namespace"; else OS << "the global scope"; + } else if (DC->isClosure()) { + OS << "block literal"; + } else if (isLambdaCallOperator(DC)) { + OS << "lambda expression"; } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { OS << ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), PrevArgs, QualTypeVals); } else { - // FIXME: Get these strings from some localized place - if (isa<BlockDecl>(DC)) { - OS << "block literal"; - break; - } - if (isLambdaCallOperator(DC)) { - OS << "lambda expression"; - break; - } + assert(isa<NamedDecl>(DC) && "Expected a NamedDecl"); NamedDecl *ND = cast<NamedDecl>(DC); if (isa<NamespaceDecl>(ND)) OS << "namespace "; @@ -877,6 +873,194 @@ class TemplateDiff { return Ty->getAs<TemplateSpecializationType>(); } + /// DiffTypes - Fills a DiffNode with information about a type difference. + void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter, + TemplateTypeParmDecl *FromDefaultTypeDecl, + TemplateTypeParmDecl *ToDefaultTypeDecl) { + QualType FromType = GetType(FromIter, FromDefaultTypeDecl); + QualType ToType = GetType(ToIter, ToDefaultTypeDecl); + + Tree.SetNode(FromType, ToType); + Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), + ToIter.isEnd() && !ToType.isNull()); + Tree.SetKind(DiffTree::Type); + if (FromType.isNull() || ToType.isNull()) + return; + + if (Context.hasSameType(FromType, ToType)) { + Tree.SetSame(true); + return; + } + + const TemplateSpecializationType *FromArgTST = + GetTemplateSpecializationType(Context, FromType); + if (!FromArgTST) + return; + + const TemplateSpecializationType *ToArgTST = + GetTemplateSpecializationType(Context, ToType); + if (!ToArgTST) + return; + + if (!hasSameTemplate(FromArgTST, ToArgTST)) + return; + + Qualifiers FromQual = FromType.getQualifiers(), + ToQual = ToType.getQualifiers(); + FromQual -= QualType(FromArgTST, 0).getQualifiers(); + ToQual -= QualType(ToArgTST, 0).getQualifiers(); + Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(), + ToArgTST->getTemplateName().getAsTemplateDecl()); + Tree.SetNode(FromQual, ToQual); + Tree.SetKind(DiffTree::Template); + DiffTemplate(FromArgTST, ToArgTST); + } + + /// DiffTemplateTemplates - Fills a DiffNode with information about a + /// template template difference. + void DiffTemplateTemplates(const TSTiterator &FromIter, + const TSTiterator &ToIter, + TemplateTemplateParmDecl *FromDefaultTemplateDecl, + TemplateTemplateParmDecl *ToDefaultTemplateDecl) { + TemplateDecl *FromDecl = GetTemplateDecl(FromIter, FromDefaultTemplateDecl); + TemplateDecl *ToDecl = GetTemplateDecl(ToIter, ToDefaultTemplateDecl); + Tree.SetNode(FromDecl, ToDecl); + Tree.SetSame(FromDecl && ToDecl && + FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); + Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl); + Tree.SetKind(DiffTree::TemplateTemplate); + } + + /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes + static void InitializeNonTypeDiffVariables( + ASTContext &Context, const TSTiterator &Iter, + NonTypeTemplateParmDecl *Default, bool &HasInt, bool &HasValueDecl, + bool &IsNullPtr, Expr *&E, llvm::APSInt &Value, ValueDecl *&VD) { + HasInt = !Iter.isEnd() && Iter->getKind() == TemplateArgument::Integral; + + HasValueDecl = + !Iter.isEnd() && Iter->getKind() == TemplateArgument::Declaration; + + IsNullPtr = !Iter.isEnd() && Iter->getKind() == TemplateArgument::NullPtr; + + if (HasInt) + Value = Iter->getAsIntegral(); + else if (HasValueDecl) + VD = Iter->getAsDecl(); + else if (!IsNullPtr) + E = GetExpr(Iter, Default); + + if (E && Default->getType()->isPointerType()) + IsNullPtr = CheckForNullPtr(Context, E); + } + + /// NeedsAddressOf - Helper function for DiffNonTypes. Returns true if the + /// ValueDecl needs a '&' when printed. + static bool NeedsAddressOf(ValueDecl *VD, Expr *E, + NonTypeTemplateParmDecl *Default) { + if (!VD) + return false; + + if (E) { + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParens())) { + if (UO->getOpcode() == UO_AddrOf) { + return true; + } + } + return false; + } + + if (!Default->getType()->isReferenceType()) { + return true; + } + + return false; + } + + /// DiffNonTypes - Handles any template parameters not handled by DiffTypes + /// of DiffTemplatesTemplates, such as integer and declaration parameters. + void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter, + NonTypeTemplateParmDecl *FromDefaultNonTypeDecl, + NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) { + Expr *FromExpr = nullptr, *ToExpr = nullptr; + llvm::APSInt FromInt, ToInt; + ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr; + bool HasFromInt = false, HasToInt = false, HasFromValueDecl = false, + HasToValueDecl = false, FromNullPtr = false, ToNullPtr = false; + InitializeNonTypeDiffVariables(Context, FromIter, FromDefaultNonTypeDecl, + HasFromInt, HasFromValueDecl, FromNullPtr, + FromExpr, FromInt, FromValueDecl); + InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, + HasToInt, HasToValueDecl, ToNullPtr, + ToExpr, ToInt, ToValueDecl); + + assert(((!HasFromInt && !HasToInt) || + (!HasFromValueDecl && !HasToValueDecl)) && + "Template argument cannot be both integer and declaration"); + + unsigned ParamWidth = 128; // Safe default + if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType()) + ParamWidth = Context.getIntWidth(FromDefaultNonTypeDecl->getType()); + + if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { + Tree.SetNode(FromExpr, ToExpr); + Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr); + if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType()) { + if (FromExpr) + HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt); + if (ToExpr) + HasToInt = GetInt(Context, ToIter, ToExpr, ToInt); + } + if (HasFromInt && HasToInt) { + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); + Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); + Tree.SetKind(DiffTree::Integer); + } else if (HasFromInt || HasToInt) { + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); + Tree.SetSame(false); + Tree.SetKind(DiffTree::Integer); + } else { + Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr) || + (FromNullPtr && ToNullPtr)); + Tree.SetNullPtr(FromNullPtr, ToNullPtr); + Tree.SetKind(DiffTree::Expression); + } + return; + } + + if (HasFromInt || HasToInt) { + if (!HasFromInt && FromExpr) + HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt); + if (!HasToInt && ToExpr) + HasToInt = GetInt(Context, ToIter, ToExpr, ToInt); + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); + Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); + Tree.SetDefault(FromIter.isEnd() && HasFromInt, + ToIter.isEnd() && HasToInt); + Tree.SetKind(DiffTree::Integer); + return; + } + + if (!HasFromValueDecl && FromExpr) + FromValueDecl = GetValueDecl(FromIter, FromExpr); + if (!HasToValueDecl && ToExpr) + ToValueDecl = GetValueDecl(ToIter, ToExpr); + + bool FromAddressOf = + NeedsAddressOf(FromValueDecl, FromExpr, FromDefaultNonTypeDecl); + bool ToAddressOf = + NeedsAddressOf(ToValueDecl, ToExpr, ToDefaultNonTypeDecl); + + Tree.SetNullPtr(FromNullPtr, ToNullPtr); + Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); + Tree.SetSame(FromValueDecl && ToValueDecl && + FromValueDecl->getCanonicalDecl() == + ToValueDecl->getCanonicalDecl()); + Tree.SetDefault(FromIter.isEnd() && FromValueDecl, + ToIter.isEnd() && ToValueDecl); + Tree.SetKind(DiffTree::Declaration); + } + /// DiffTemplate - recursively visits template arguments and stores the /// argument info into a tree. void DiffTemplate(const TemplateSpecializationType *FromTST, @@ -894,191 +1078,33 @@ class TemplateDiff { // Get the parameter at index TotalArgs. If index is larger // than the total number of parameters, then there is an // argument pack, so re-use the last parameter. - unsigned ParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1); - NamedDecl *ParamND = ParamsFrom->getParam(ParamIndex); - - // Handle Types - if (TemplateTypeParmDecl *DefaultTTPD = - dyn_cast<TemplateTypeParmDecl>(ParamND)) { - QualType FromType, ToType; - FromType = GetType(FromIter, DefaultTTPD); - // A forward declaration can have no default arg but the actual class - // can, don't mix up iterators and get the original parameter. - ToType = GetType( - ToIter, cast<TemplateTypeParmDecl>(ParamsTo->getParam(ParamIndex))); - Tree.SetNode(FromType, ToType); - Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), - ToIter.isEnd() && !ToType.isNull()); - Tree.SetKind(DiffTree::Type); - if (!FromType.isNull() && !ToType.isNull()) { - if (Context.hasSameType(FromType, ToType)) { - Tree.SetSame(true); - } else { - Qualifiers FromQual = FromType.getQualifiers(), - ToQual = ToType.getQualifiers(); - const TemplateSpecializationType *FromArgTST = - GetTemplateSpecializationType(Context, FromType); - const TemplateSpecializationType *ToArgTST = - GetTemplateSpecializationType(Context, ToType); - - if (FromArgTST && ToArgTST && - hasSameTemplate(FromArgTST, ToArgTST)) { - FromQual -= QualType(FromArgTST, 0).getQualifiers(); - ToQual -= QualType(ToArgTST, 0).getQualifiers(); - Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(), - ToArgTST->getTemplateName().getAsTemplateDecl()); - Tree.SetNode(FromQual, ToQual); - Tree.SetKind(DiffTree::Template); - DiffTemplate(FromArgTST, ToArgTST); - } - } - } - } - - // Handle Expressions - if (NonTypeTemplateParmDecl *DefaultNTTPD = - dyn_cast<NonTypeTemplateParmDecl>(ParamND)) { - Expr *FromExpr = nullptr, *ToExpr = nullptr; - llvm::APSInt FromInt, ToInt; - ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr; - unsigned ParamWidth = 128; // Safe default - if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) - ParamWidth = Context.getIntWidth(DefaultNTTPD->getType()); - bool HasFromInt = !FromIter.isEnd() && - FromIter->getKind() == TemplateArgument::Integral; - bool HasToInt = !ToIter.isEnd() && - ToIter->getKind() == TemplateArgument::Integral; - bool HasFromValueDecl = - !FromIter.isEnd() && - FromIter->getKind() == TemplateArgument::Declaration; - bool HasToValueDecl = - !ToIter.isEnd() && - ToIter->getKind() == TemplateArgument::Declaration; - bool FromNullPtr = !FromIter.isEnd() && - FromIter->getKind() == TemplateArgument::NullPtr; - bool ToNullPtr = - !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::NullPtr; - - assert(((!HasFromInt && !HasToInt) || - (!HasFromValueDecl && !HasToValueDecl)) && - "Template argument cannot be both integer and declaration"); - - if (HasFromInt) - FromInt = FromIter->getAsIntegral(); - else if (HasFromValueDecl) - FromValueDecl = FromIter->getAsDecl(); - else if (!FromNullPtr) - FromExpr = GetExpr(FromIter, DefaultNTTPD); - - if (HasToInt) - ToInt = ToIter->getAsIntegral(); - else if (HasToValueDecl) - ToValueDecl = ToIter->getAsDecl(); - else if (!ToNullPtr) - ToExpr = GetExpr(ToIter, DefaultNTTPD); - - bool TemplateArgumentIsPointerType = - DefaultNTTPD->getType()->isPointerType(); - if (FromExpr && TemplateArgumentIsPointerType) { - FromNullPtr = CheckForNullPtr(FromExpr); - } - if (ToExpr && TemplateArgumentIsPointerType) { - ToNullPtr = CheckForNullPtr(ToExpr); - } - - if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { - Tree.SetNode(FromExpr, ToExpr); - Tree.SetDefault(FromIter.isEnd() && FromExpr, - ToIter.isEnd() && ToExpr); - if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) { - if (FromExpr) - HasFromInt = GetInt(FromIter, FromExpr, FromInt); - if (ToExpr) - HasToInt = GetInt(ToIter, ToExpr, ToInt); - } - if (HasFromInt && HasToInt) { - Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); - Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); - Tree.SetKind(DiffTree::Integer); - } else if (HasFromInt || HasToInt) { - Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); - Tree.SetSame(false); - Tree.SetKind(DiffTree::Integer); - } else { - Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr) || - (FromNullPtr && ToNullPtr)); - Tree.SetNullPtr(FromNullPtr, ToNullPtr); - Tree.SetKind(DiffTree::Expression); - } - } else if (HasFromInt || HasToInt) { - if (!HasFromInt && FromExpr) - HasFromInt = GetInt(FromIter, FromExpr, FromInt); - if (!HasToInt && ToExpr) - HasToInt = GetInt(ToIter, ToExpr, ToInt); - Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); - Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); - Tree.SetDefault(FromIter.isEnd() && HasFromInt, - ToIter.isEnd() && HasToInt); - Tree.SetKind(DiffTree::Integer); - } else { - if (!HasFromValueDecl && FromExpr) - FromValueDecl = GetValueDecl(FromIter, FromExpr); - if (!HasToValueDecl && ToExpr) - ToValueDecl = GetValueDecl(ToIter, ToExpr); - QualType ArgumentType = DefaultNTTPD->getType(); - bool FromAddressOf = false; - if (FromValueDecl) { - if (FromExpr) { - if (UnaryOperator *UO = - dyn_cast<UnaryOperator>(FromExpr->IgnoreParens())) { - if (UO->getOpcode() == UO_AddrOf) - FromAddressOf = true; - } - } else { - if (!ArgumentType->isReferenceType()) { - FromAddressOf = true; - } - } - } - bool ToAddressOf = false; - if (ToValueDecl) { - if (ToExpr) { - if (UnaryOperator *UO = - dyn_cast<UnaryOperator>(ToExpr->IgnoreParens())) { - if (UO->getOpcode() == UO_AddrOf) { - ToAddressOf = true; - } - } - } else { - if (!ArgumentType->isReferenceType()) { - ToAddressOf = true; - } - } - } - Tree.SetNullPtr(FromNullPtr, ToNullPtr); - Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); - Tree.SetSame(FromValueDecl && ToValueDecl && - FromValueDecl->getCanonicalDecl() == - ToValueDecl->getCanonicalDecl()); - Tree.SetDefault(FromIter.isEnd() && FromValueDecl, - ToIter.isEnd() && ToValueDecl); - Tree.SetKind(DiffTree::Declaration); - } - } - - // Handle Templates - if (TemplateTemplateParmDecl *DefaultTTPD = - dyn_cast<TemplateTemplateParmDecl>(ParamND)) { - TemplateDecl *FromDecl, *ToDecl; - FromDecl = GetTemplateDecl(FromIter, DefaultTTPD); - ToDecl = GetTemplateDecl(ToIter, DefaultTTPD); - Tree.SetNode(FromDecl, ToDecl); - Tree.SetSame( - FromDecl && ToDecl && - FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); - Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl); - Tree.SetKind(DiffTree::TemplateTemplate); - } + unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1); + unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1); + NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex); + NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex); + + TemplateTypeParmDecl *FromDefaultTypeDecl = + dyn_cast<TemplateTypeParmDecl>(FromParamND); + TemplateTypeParmDecl *ToDefaultTypeDecl = + dyn_cast<TemplateTypeParmDecl>(ToParamND); + if (FromDefaultTypeDecl && ToDefaultTypeDecl) + DiffTypes(FromIter, ToIter, FromDefaultTypeDecl, ToDefaultTypeDecl); + + TemplateTemplateParmDecl *FromDefaultTemplateDecl = + dyn_cast<TemplateTemplateParmDecl>(FromParamND); + TemplateTemplateParmDecl *ToDefaultTemplateDecl = + dyn_cast<TemplateTemplateParmDecl>(ToParamND); + if (FromDefaultTemplateDecl && ToDefaultTemplateDecl) + DiffTemplateTemplates(FromIter, ToIter, FromDefaultTemplateDecl, + ToDefaultTemplateDecl); + + NonTypeTemplateParmDecl *FromDefaultNonTypeDecl = + dyn_cast<NonTypeTemplateParmDecl>(FromParamND); + NonTypeTemplateParmDecl *ToDefaultNonTypeDecl = + dyn_cast<NonTypeTemplateParmDecl>(ToParamND); + if (FromDefaultNonTypeDecl && ToDefaultNonTypeDecl) + DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl, + ToDefaultNonTypeDecl); ++FromIter; ++ToIter; @@ -1147,7 +1173,8 @@ class TemplateDiff { /// GetType - Retrieves the template type arguments, including default /// arguments. - QualType GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD) { + static QualType GetType(const TSTiterator &Iter, + TemplateTypeParmDecl *DefaultTTPD) { bool isVariadic = DefaultTTPD->isParameterPack(); if (!Iter.isEnd()) @@ -1164,7 +1191,8 @@ class TemplateDiff { /// GetExpr - Retrieves the template expression argument, including default /// arguments. - Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) { + static Expr *GetExpr(const TSTiterator &Iter, + NonTypeTemplateParmDecl *DefaultNTTPD) { Expr *ArgExpr = nullptr; bool isVariadic = DefaultNTTPD->isParameterPack(); @@ -1183,7 +1211,8 @@ class TemplateDiff { /// GetInt - Retrieves the template integer argument, including evaluating /// default arguments. - bool GetInt(const TSTiterator &Iter, Expr *ArgExpr, llvm::APInt &Int) { + static bool GetInt(ASTContext &Context, const TSTiterator &Iter, + Expr *ArgExpr, llvm::APInt &Int) { // Default, value-depenedent expressions require fetching // from the desugared TemplateArgument, otherwise expression needs to // be evaluatable. @@ -1209,7 +1238,7 @@ class TemplateDiff { /// GetValueDecl - Retrieves the template Decl argument, including /// default expression argument. - ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { + static ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { // Default, value-depenedent expressions require fetching // from the desugared TemplateArgument if (Iter.isEnd() && ArgExpr->isValueDependent()) @@ -1235,7 +1264,7 @@ class TemplateDiff { /// CheckForNullPtr - returns true if the expression can be evaluated as /// a null pointer - bool CheckForNullPtr(Expr *E) { + static bool CheckForNullPtr(ASTContext &Context, Expr *E) { assert(E && "Expected expression"); E = E->IgnoreParenCasts(); @@ -1256,7 +1285,7 @@ class TemplateDiff { /// GetTemplateDecl - Retrieves the template template arguments, including /// default arguments. - TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, + static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, TemplateTemplateParmDecl *DefaultTTPD) { bool isVariadic = DefaultTTPD->isParameterPack(); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp index df7a2cb..ebf5e65 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp @@ -20,6 +20,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeVisitor.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/raw_ostream.h" @@ -90,24 +91,22 @@ namespace { class ASTDumper : public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>, - public ConstCommentVisitor<ASTDumper> { + public ConstCommentVisitor<ASTDumper>, public TypeVisitor<ASTDumper> { raw_ostream &OS; const CommandTraits *Traits; const SourceManager *SM; - bool IsFirstLine; - // Indicates whether more child are expected at the current tree depth - enum IndentType { IT_Child, IT_LastChild }; + /// Pending[i] is an action to dump an entity at level i. + llvm::SmallVector<std::function<void(bool isLastChild)>, 32> Pending; - /// Indents[i] indicates if another child exists at level i. - /// Used by Indent() to print the tree structure. - llvm::SmallVector<IndentType, 32> Indents; + /// Indicates whether we're at the top level. + bool TopLevel; - /// Indicates that more children will be needed at this indent level. - /// If true, prevents lastChild() from marking the node as the last child. - /// This is used when there are multiple collections of children to be - /// dumped as well as during conditional node dumping. - bool MoreChildren; + /// Indicates if we're handling the first child after entering a new depth. + bool FirstChild; + + /// Prefix for currently-being-dumped entity. + std::string Prefix; /// Keep track of the last location we print out so that we can /// print out deltas from then on out. @@ -119,21 +118,70 @@ namespace { bool ShowColors; - class IndentScope { - ASTDumper &Dumper; - // Preserve the Dumper's MoreChildren value from the previous IndentScope - bool MoreChildren; - public: - IndentScope(ASTDumper &Dumper) : Dumper(Dumper) { - MoreChildren = Dumper.hasMoreChildren(); - Dumper.setMoreChildren(false); - Dumper.indent(); + /// Dump a child of the current node. + template<typename Fn> void dumpChild(Fn doDumpChild) { + // If we're at the top level, there's nothing interesting to do; just + // run the dumper. + if (TopLevel) { + TopLevel = false; + doDumpChild(); + while (!Pending.empty()) { + Pending.back()(true); + Pending.pop_back(); + } + Prefix.clear(); + OS << "\n"; + TopLevel = true; + return; } - ~IndentScope() { - Dumper.setMoreChildren(MoreChildren); - Dumper.unindent(); + + const FullComment *OrigFC = FC; + auto dumpWithIndent = [this, doDumpChild, OrigFC](bool isLastChild) { + // Print out the appropriate tree structure and work out the prefix for + // children of this node. For instance: + // + // A Prefix = "" + // |-B Prefix = "| " + // | `-C Prefix = "| " + // `-D Prefix = " " + // |-E Prefix = " | " + // `-F Prefix = " " + // G Prefix = "" + // + // Note that the first level gets no prefix. + { + OS << '\n'; + ColorScope Color(*this, IndentColor); + OS << Prefix << (isLastChild ? '`' : '|') << '-'; + this->Prefix.push_back(isLastChild ? ' ' : '|'); + this->Prefix.push_back(' '); + } + + FirstChild = true; + unsigned Depth = Pending.size(); + + FC = OrigFC; + doDumpChild(); + + // If any children are left, they're the last at their nesting level. + // Dump those ones out now. + while (Depth < Pending.size()) { + Pending.back()(true); + this->Pending.pop_back(); + } + + // Restore the old prefix. + this->Prefix.resize(Prefix.size() - 2); + }; + + if (FirstChild) { + Pending.push_back(std::move(dumpWithIndent)); + } else { + Pending.back()(false); + Pending.back() = std::move(dumpWithIndent); } - }; + FirstChild = false; + } class ColorScope { ASTDumper &Dumper; @@ -149,78 +197,37 @@ namespace { } }; - class ChildDumper { - ASTDumper &Dumper; - - const Decl *Prev; - bool PrevRef; - public: - ChildDumper(ASTDumper &Dumper) : Dumper(Dumper), Prev(nullptr) {} - ~ChildDumper() { - if (Prev) { - Dumper.lastChild(); - dump(nullptr); - } - } - - // FIXME: This should take an arbitrary callable as the dumping action. - void dump(const Decl *D, bool Ref = false) { - if (Prev) { - if (PrevRef) - Dumper.dumpDeclRef(Prev); - else - Dumper.dumpDecl(Prev); - } - Prev = D; - PrevRef = Ref; - } - void dumpRef(const Decl *D) { dump(D, true); } - - // Give up ownership of the children of the node. By calling this, - // the caller takes back responsibility for calling lastChild(). - void release() { dump(nullptr); } - }; - public: ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) - : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false), + : OS(OS), Traits(Traits), SM(SM), TopLevel(true), FirstChild(true), LastLocFilename(""), LastLocLine(~0U), FC(nullptr), ShowColors(SM && SM->getDiagnostics().getShowColors()) { } ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM, bool ShowColors) - : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false), + : OS(OS), Traits(Traits), SM(SM), TopLevel(true), FirstChild(true), LastLocFilename(""), LastLocLine(~0U), ShowColors(ShowColors) { } - ~ASTDumper() { - OS << "\n"; - } - void dumpDecl(const Decl *D); void dumpStmt(const Stmt *S); void dumpFullComment(const FullComment *C); - // Formatting - void indent(); - void unindent(); - void lastChild(); - bool hasMoreChildren(); - void setMoreChildren(bool Value); - // Utilities void dumpPointer(const void *Ptr); void dumpSourceRange(SourceRange R); void dumpLocation(SourceLocation Loc); - void dumpBareType(QualType T); + void dumpBareType(QualType T, bool Desugar = true); void dumpType(QualType T); + void dumpTypeAsChild(QualType T); + void dumpTypeAsChild(const Type *T); void dumpBareDeclRef(const Decl *Node); void dumpDeclRef(const Decl *Node, const char *Label = nullptr); void dumpName(const NamedDecl *D); bool hasNodes(const DeclContext *DC); void dumpDeclContext(const DeclContext *DC); - void dumpLookups(const DeclContext *DC); + void dumpLookups(const DeclContext *DC, bool DumpDecls); void dumpAttr(const Attr *A); // C++ Utilities @@ -233,6 +240,175 @@ namespace { void dumpTemplateArgument(const TemplateArgument &A, SourceRange R = SourceRange()); + // Types + void VisitComplexType(const ComplexType *T) { + dumpTypeAsChild(T->getElementType()); + } + void VisitPointerType(const PointerType *T) { + dumpTypeAsChild(T->getPointeeType()); + } + void VisitBlockPointerType(const BlockPointerType *T) { + dumpTypeAsChild(T->getPointeeType()); + } + void VisitReferenceType(const ReferenceType *T) { + dumpTypeAsChild(T->getPointeeType()); + } + void VisitRValueReferenceType(const ReferenceType *T) { + if (T->isSpelledAsLValue()) + OS << " written as lvalue reference"; + VisitReferenceType(T); + } + void VisitMemberPointerType(const MemberPointerType *T) { + dumpTypeAsChild(T->getClass()); + dumpTypeAsChild(T->getPointeeType()); + } + void VisitArrayType(const ArrayType *T) { + switch (T->getSizeModifier()) { + case ArrayType::Normal: break; + case ArrayType::Static: OS << " static"; break; + case ArrayType::Star: OS << " *"; break; + } + OS << " " << T->getIndexTypeQualifiers().getAsString(); + dumpTypeAsChild(T->getElementType()); + } + void VisitConstantArrayType(const ConstantArrayType *T) { + OS << " " << T->getSize(); + VisitArrayType(T); + } + void VisitVariableArrayType(const VariableArrayType *T) { + OS << " "; + dumpSourceRange(T->getBracketsRange()); + VisitArrayType(T); + dumpStmt(T->getSizeExpr()); + } + void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { + VisitArrayType(T); + OS << " "; + dumpSourceRange(T->getBracketsRange()); + dumpStmt(T->getSizeExpr()); + } + void VisitDependentSizedExtVectorType( + const DependentSizedExtVectorType *T) { + OS << " "; + dumpLocation(T->getAttributeLoc()); + dumpTypeAsChild(T->getElementType()); + dumpStmt(T->getSizeExpr()); + } + void VisitVectorType(const VectorType *T) { + switch (T->getVectorKind()) { + case VectorType::GenericVector: break; + case VectorType::AltiVecVector: OS << " altivec"; break; + case VectorType::AltiVecPixel: OS << " altivec pixel"; break; + case VectorType::AltiVecBool: OS << " altivec bool"; break; + case VectorType::NeonVector: OS << " neon"; break; + case VectorType::NeonPolyVector: OS << " neon poly"; break; + } + OS << " " << T->getNumElements(); + dumpTypeAsChild(T->getElementType()); + } + void VisitFunctionType(const FunctionType *T) { + auto EI = T->getExtInfo(); + if (EI.getNoReturn()) OS << " noreturn"; + if (EI.getProducesResult()) OS << " produces_result"; + if (EI.getHasRegParm()) OS << " regparm " << EI.getRegParm(); + OS << " " << FunctionType::getNameForCallConv(EI.getCC()); + dumpTypeAsChild(T->getReturnType()); + } + void VisitFunctionProtoType(const FunctionProtoType *T) { + auto EPI = T->getExtProtoInfo(); + if (EPI.HasTrailingReturn) OS << " trailing_return"; + if (T->isConst()) OS << " const"; + if (T->isVolatile()) OS << " volatile"; + if (T->isRestrict()) OS << " restrict"; + switch (EPI.RefQualifier) { + case RQ_None: break; + case RQ_LValue: OS << " &"; break; + case RQ_RValue: OS << " &&"; break; + } + // FIXME: Exception specification. + // FIXME: Consumed parameters. + VisitFunctionType(T); + for (QualType PT : T->getParamTypes()) + dumpTypeAsChild(PT); + if (EPI.Variadic) + dumpChild([=] { OS << "..."; }); + } + void VisitUnresolvedUsingType(const UnresolvedUsingType *T) { + dumpDeclRef(T->getDecl()); + } + void VisitTypedefType(const TypedefType *T) { + dumpDeclRef(T->getDecl()); + } + void VisitTypeOfExprType(const TypeOfExprType *T) { + dumpStmt(T->getUnderlyingExpr()); + } + void VisitDecltypeType(const DecltypeType *T) { + dumpStmt(T->getUnderlyingExpr()); + } + void VisitUnaryTransformType(const UnaryTransformType *T) { + switch (T->getUTTKind()) { + case UnaryTransformType::EnumUnderlyingType: + OS << " underlying_type"; + break; + } + dumpTypeAsChild(T->getBaseType()); + } + void VisitTagType(const TagType *T) { + dumpDeclRef(T->getDecl()); + } + void VisitAttributedType(const AttributedType *T) { + // FIXME: AttrKind + dumpTypeAsChild(T->getModifiedType()); + } + void VisitTemplateTypeParmType(const TemplateTypeParmType *T) { + OS << " depth " << T->getDepth() << " index " << T->getIndex(); + if (T->isParameterPack()) OS << " pack"; + dumpDeclRef(T->getDecl()); + } + void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { + dumpTypeAsChild(T->getReplacedParameter()); + } + void VisitSubstTemplateTypeParmPackType( + const SubstTemplateTypeParmPackType *T) { + dumpTypeAsChild(T->getReplacedParameter()); + dumpTemplateArgument(T->getArgumentPack()); + } + void VisitAutoType(const AutoType *T) { + if (T->isDecltypeAuto()) OS << " decltype(auto)"; + if (!T->isDeduced()) + OS << " undeduced"; + } + void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { + if (T->isTypeAlias()) OS << " alias"; + OS << " "; T->getTemplateName().dump(OS); + for (auto &Arg : *T) + dumpTemplateArgument(Arg); + if (T->isTypeAlias()) + dumpTypeAsChild(T->getAliasedType()); + } + void VisitInjectedClassNameType(const InjectedClassNameType *T) { + dumpDeclRef(T->getDecl()); + } + void VisitObjCInterfaceType(const ObjCInterfaceType *T) { + dumpDeclRef(T->getDecl()); + } + void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { + dumpTypeAsChild(T->getPointeeType()); + } + void VisitAtomicType(const AtomicType *T) { + dumpTypeAsChild(T->getValueType()); + } + void VisitAdjustedType(const AdjustedType *T) { + dumpTypeAsChild(T->getOriginalType()); + } + void VisitPackExpansionType(const PackExpansionType *T) { + if (auto N = T->getNumExpansions()) OS << " expansions " << *N; + if (!T->isSugared()) + dumpTypeAsChild(T->getPattern()); + } + // FIXME: ElaboratedType, DependentNameType, + // DependentTemplateSpecializationType, ObjCObjectType + // Decls void VisitLabelDecl(const LabelDecl *D); void VisitTypedefDecl(const TypedefDecl *D); @@ -255,8 +431,7 @@ namespace { void VisitCXXRecordDecl(const CXXRecordDecl *D); void VisitStaticAssertDecl(const StaticAssertDecl *D); template<typename SpecializationDecl> - void VisitTemplateDeclSpecialization(ChildDumper &Children, - const SpecializationDecl *D, + void VisitTemplateDeclSpecialization(const SpecializationDecl *D, bool DumpExplicitInst, bool DumpRefOnly); template<typename TemplateDecl> @@ -378,67 +553,6 @@ namespace { // Utilities //===----------------------------------------------------------------------===// -// Print out the appropriate tree structure using the Indents vector. -// Example of tree and the Indents vector at each level. -// A { } -// |-B { IT_Child } -// | `-C { IT_Child, IT_LastChild } -// `-D { IT_LastChild } -// |-E { IT_LastChild, IT_Child } -// `-F { IT_LastChild, IT_LastChild } -// Type non-last element, last element -// IT_Child "| " "|-" -// IT_LastChild " " "`-" -void ASTDumper::indent() { - if (IsFirstLine) - IsFirstLine = false; - else - OS << "\n"; - - ColorScope Color(*this, IndentColor); - for (SmallVectorImpl<IndentType>::const_iterator I = Indents.begin(), - E = Indents.end(); - I != E; ++I) { - switch (*I) { - case IT_Child: - if (I == E - 1) - OS << "|-"; - else - OS << "| "; - continue; - case IT_LastChild: - if (I == E - 1) - OS << "`-"; - else - OS << " "; - continue; - } - llvm_unreachable("Invalid IndentType"); - } - Indents.push_back(IT_Child); -} - -void ASTDumper::unindent() { - Indents.pop_back(); -} - -// Call before each potential last child node is to be dumped. If MoreChildren -// is false, then this is the last child, otherwise treat as a regular node. -void ASTDumper::lastChild() { - if (!hasMoreChildren()) - Indents.back() = IT_LastChild; -} - -// MoreChildren should be set before calling another function that may print -// additional nodes to prevent conflicting final child nodes. -bool ASTDumper::hasMoreChildren() { - return MoreChildren; -} - -void ASTDumper::setMoreChildren(bool Value) { - MoreChildren = Value; -} - void ASTDumper::dumpPointer(const void *Ptr) { ColorScope Color(*this, AddressColor); OS << ' ' << Ptr; @@ -491,13 +605,13 @@ void ASTDumper::dumpSourceRange(SourceRange R) { } -void ASTDumper::dumpBareType(QualType T) { +void ASTDumper::dumpBareType(QualType T, bool Desugar) { ColorScope Color(*this, TypeColor); - + SplitQualType T_split = T.split(); OS << "'" << QualType::getAsString(T_split) << "'"; - if (!T.isNull()) { + if (Desugar && !T.isNull()) { // If the type is sugared, also dump a (shallow) desugared type. SplitQualType D_split = T.getSplitDesugaredType(); if (T_split != D_split) @@ -510,6 +624,59 @@ void ASTDumper::dumpType(QualType T) { dumpBareType(T); } +void ASTDumper::dumpTypeAsChild(QualType T) { + SplitQualType SQT = T.split(); + if (!SQT.Quals.hasQualifiers()) + return dumpTypeAsChild(SQT.Ty); + + dumpChild([=] { + OS << "QualType"; + dumpPointer(T.getAsOpaquePtr()); + OS << " "; + dumpBareType(T, false); + OS << " " << T.split().Quals.getAsString(); + dumpTypeAsChild(T.split().Ty); + }); +} + +void ASTDumper::dumpTypeAsChild(const Type *T) { + dumpChild([=] { + if (!T) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } + + { + ColorScope Color(*this, TypeColor); + OS << T->getTypeClassName() << "Type"; + } + dumpPointer(T); + OS << " "; + dumpBareType(QualType(T, 0), false); + + QualType SingleStepDesugar = + T->getLocallyUnqualifiedSingleStepDesugaredType(); + if (SingleStepDesugar != QualType(T, 0)) + OS << " sugar"; + if (T->isDependentType()) + OS << " dependent"; + else if (T->isInstantiationDependentType()) + OS << " instantiation_dependent"; + if (T->isVariablyModifiedType()) + OS << " variably_modified"; + if (T->containsUnexpandedParameterPack()) + OS << " contains_unexpanded_pack"; + if (T->isFromAST()) + OS << " imported"; + + TypeVisitor<ASTDumper>::Visit(T); + + if (SingleStepDesugar != QualType(T, 0)) + dumpTypeAsChild(SingleStepDesugar); + }); +} + void ASTDumper::dumpBareDeclRef(const Decl *D) { { ColorScope Color(*this, DeclKindNameColor); @@ -530,10 +697,11 @@ void ASTDumper::dumpDeclRef(const Decl *D, const char *Label) { if (!D) return; - IndentScope Indent(*this); - if (Label) - OS << Label << ' '; - dumpBareDeclRef(D); + dumpChild([=]{ + if (Label) + OS << Label << ' '; + dumpBareDeclRef(D); + }); } void ASTDumper::dumpName(const NamedDecl *ND) { @@ -555,86 +723,96 @@ void ASTDumper::dumpDeclContext(const DeclContext *DC) { if (!DC) return; - ChildDumper Children(*this); for (auto *D : DC->noload_decls()) - Children.dump(D); + dumpDecl(D); if (DC->hasExternalLexicalStorage()) { - Children.release(); - - lastChild(); - IndentScope Indent(*this); - ColorScope Color(*this, UndeserializedColor); - OS << "<undeserialized declarations>"; + dumpChild([=]{ + ColorScope Color(*this, UndeserializedColor); + OS << "<undeserialized declarations>"; + }); } } -void ASTDumper::dumpLookups(const DeclContext *DC) { - IndentScope Indent(*this); +void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { + dumpChild([=] { + OS << "StoredDeclsMap "; + dumpBareDeclRef(cast<Decl>(DC)); - OS << "StoredDeclsMap "; - dumpBareDeclRef(cast<Decl>(DC)); + const DeclContext *Primary = DC->getPrimaryContext(); + if (Primary != DC) { + OS << " primary"; + dumpPointer(cast<Decl>(Primary)); + } - const DeclContext *Primary = DC->getPrimaryContext(); - if (Primary != DC) { - OS << " primary"; - dumpPointer(cast<Decl>(Primary)); - } + bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage(); - bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage(); + DeclContext::all_lookups_iterator I = Primary->noload_lookups_begin(), + E = Primary->noload_lookups_end(); + while (I != E) { + DeclarationName Name = I.getLookupName(); + DeclContextLookupResult R = *I++; - DeclContext::all_lookups_iterator I = Primary->noload_lookups_begin(), - E = Primary->noload_lookups_end(); - while (I != E) { - DeclarationName Name = I.getLookupName(); - DeclContextLookupResult R = *I++; - if (I == E && !HasUndeserializedLookups) - lastChild(); + dumpChild([=] { + OS << "DeclarationName "; + { + ColorScope Color(*this, DeclNameColor); + OS << '\'' << Name << '\''; + } - IndentScope Indent(*this); - OS << "DeclarationName "; - { - ColorScope Color(*this, DeclNameColor); - OS << '\'' << Name << '\''; + for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end(); + RI != RE; ++RI) { + dumpChild([=] { + dumpBareDeclRef(*RI); + + if ((*RI)->isHidden()) + OS << " hidden"; + + // If requested, dump the redecl chain for this lookup. + if (DumpDecls) { + // Dump earliest decl first. + std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) { + if (Decl *Prev = D->getPreviousDecl()) + DumpWithPrev(Prev); + dumpDecl(D); + }; + DumpWithPrev(*RI); + } + }); + } + }); } - for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end(); - RI != RE; ++RI) { - if (RI + 1 == RE) - lastChild(); - dumpDeclRef(*RI); - if ((*RI)->isHidden()) - OS << " hidden"; + if (HasUndeserializedLookups) { + dumpChild([=] { + ColorScope Color(*this, UndeserializedColor); + OS << "<undeserialized lookups>"; + }); } - } - - if (HasUndeserializedLookups) { - lastChild(); - IndentScope Indent(*this); - ColorScope Color(*this, UndeserializedColor); - OS << "<undeserialized lookups>"; - } + }); } void ASTDumper::dumpAttr(const Attr *A) { - IndentScope Indent(*this); - { - ColorScope Color(*this, AttrColor); + dumpChild([=] { + { + ColorScope Color(*this, AttrColor); - switch (A->getKind()) { + switch (A->getKind()) { #define ATTR(X) case attr::X: OS << #X; break; #include "clang/Basic/AttrList.inc" - default: llvm_unreachable("unexpected attribute kind"); + default: + llvm_unreachable("unexpected attribute kind"); + } + OS << "Attr"; } - OS << "Attr"; - } - dumpPointer(A); - dumpSourceRange(A->getRange()); - if (A->isInherited()) - OS << " Inherited"; - if (A->isImplicit()) - OS << " Implicit"; + dumpPointer(A); + dumpSourceRange(A->getRange()); + if (A->isInherited()) + OS << " Inherited"; + if (A->isImplicit()) + OS << " Implicit"; #include "clang/AST/AttrDump.inc" + }); } static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {} @@ -687,15 +865,20 @@ void ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) { } void ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) { - IndentScope Indent(*this); - OS << "CXXCtorInitializer"; - if (Init->isAnyMemberInitializer()) { - OS << ' '; - dumpBareDeclRef(Init->getAnyMember()); - } else { - dumpType(QualType(Init->getBaseClass(), 0)); - } - dumpStmt(Init->getInit()); + dumpChild([=] { + OS << "CXXCtorInitializer"; + if (Init->isAnyMemberInitializer()) { + OS << ' '; + dumpBareDeclRef(Init->getAnyMember()); + } else if (Init->isBaseInitializer()) { + dumpType(QualType(Init->getBaseClass(), 0)); + } else if (Init->isDelegatingInitializer()) { + dumpType(Init->getTypeSourceInfo()->getType()); + } else { + llvm_unreachable("Unknown initializer type"); + } + dumpStmt(Init->getInit()); + }); } void ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) { @@ -709,11 +892,8 @@ void ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) { void ASTDumper::dumpTemplateArgumentListInfo( const TemplateArgumentListInfo &TALI) { - for (unsigned i = 0, e = TALI.size(); i < e; ++i) { - if (i + 1 == e) - lastChild(); + for (unsigned i = 0, e = TALI.size(); i < e; ++i) dumpTemplateArgumentLoc(TALI[i]); - } } void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) { @@ -726,54 +906,49 @@ void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) { } void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { - IndentScope Indent(*this); - OS << "TemplateArgument"; - if (R.isValid()) - dumpSourceRange(R); - - switch (A.getKind()) { - case TemplateArgument::Null: - OS << " null"; - break; - case TemplateArgument::Type: - OS << " type"; - lastChild(); - dumpType(A.getAsType()); - break; - case TemplateArgument::Declaration: - OS << " decl"; - lastChild(); - dumpDeclRef(A.getAsDecl()); - break; - case TemplateArgument::NullPtr: - OS << " nullptr"; - break; - case TemplateArgument::Integral: - OS << " integral " << A.getAsIntegral(); - break; - case TemplateArgument::Template: - OS << " template "; - A.getAsTemplate().dump(OS); - break; - case TemplateArgument::TemplateExpansion: - OS << " template expansion"; - A.getAsTemplateOrTemplatePattern().dump(OS); - break; - case TemplateArgument::Expression: - OS << " expr"; - lastChild(); - dumpStmt(A.getAsExpr()); - break; - case TemplateArgument::Pack: - OS << " pack"; - for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpTemplateArgument(*I); + dumpChild([=] { + OS << "TemplateArgument"; + if (R.isValid()) + dumpSourceRange(R); + + switch (A.getKind()) { + case TemplateArgument::Null: + OS << " null"; + break; + case TemplateArgument::Type: + OS << " type"; + dumpType(A.getAsType()); + break; + case TemplateArgument::Declaration: + OS << " decl"; + dumpDeclRef(A.getAsDecl()); + break; + case TemplateArgument::NullPtr: + OS << " nullptr"; + break; + case TemplateArgument::Integral: + OS << " integral " << A.getAsIntegral(); + break; + case TemplateArgument::Template: + OS << " template "; + A.getAsTemplate().dump(OS); + break; + case TemplateArgument::TemplateExpansion: + OS << " template expansion"; + A.getAsTemplateOrTemplatePattern().dump(OS); + break; + case TemplateArgument::Expression: + OS << " expr"; + dumpStmt(A.getAsExpr()); + break; + case TemplateArgument::Pack: + OS << " pack"; + for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); + I != E; ++I) + dumpTemplateArgument(*I); + break; } - break; - } + }); } //===----------------------------------------------------------------------===// @@ -781,64 +956,57 @@ void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { //===----------------------------------------------------------------------===// void ASTDumper::dumpDecl(const Decl *D) { - IndentScope Indent(*this); + dumpChild([=] { + if (!D) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } - if (!D) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>>"; - return; - } + { + ColorScope Color(*this, DeclKindNameColor); + OS << D->getDeclKindName() << "Decl"; + } + dumpPointer(D); + if (D->getLexicalDeclContext() != D->getDeclContext()) + OS << " parent " << cast<Decl>(D->getDeclContext()); + dumpPreviousDecl(OS, D); + dumpSourceRange(D->getSourceRange()); + OS << ' '; + dumpLocation(D->getLocation()); + if (Module *M = D->getOwningModule()) + OS << " in " << M->getFullModuleName(); + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) + if (ND->isHidden()) + OS << " hidden"; + if (D->isImplicit()) + OS << " implicit"; + if (D->isUsed()) + OS << " used"; + else if (D->isThisDeclarationReferenced()) + OS << " referenced"; + if (D->isInvalidDecl()) + OS << " invalid"; + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isConstexpr()) + OS << " constexpr"; - { - ColorScope Color(*this, DeclKindNameColor); - OS << D->getDeclKindName() << "Decl"; - } - dumpPointer(D); - if (D->getLexicalDeclContext() != D->getDeclContext()) - OS << " parent " << cast<Decl>(D->getDeclContext()); - dumpPreviousDecl(OS, D); - dumpSourceRange(D->getSourceRange()); - OS << ' '; - dumpLocation(D->getLocation()); - if (Module *M = D->getOwningModule()) - OS << " in " << M->getFullModuleName(); - if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) - if (ND->isHidden()) - OS << " hidden"; - if (D->isImplicit()) - OS << " implicit"; - if (D->isUsed()) - OS << " used"; - else if (D->isReferenced()) - OS << " referenced"; - if (D->isInvalidDecl()) - OS << " invalid"; - - bool HasAttrs = D->hasAttrs(); - const FullComment *Comment = - D->getASTContext().getLocalCommentForDeclUncached(D); - // Decls within functions are visited by the body - bool HasDeclContext = !isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) && - hasNodes(dyn_cast<DeclContext>(D)); - - setMoreChildren(HasAttrs || Comment || HasDeclContext); - ConstDeclVisitor<ASTDumper>::Visit(D); - - setMoreChildren(Comment || HasDeclContext); - for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpAttr(*I); - } - setMoreChildren(HasDeclContext); - lastChild(); - dumpFullComment(Comment); + ConstDeclVisitor<ASTDumper>::Visit(D); - setMoreChildren(false); - if (HasDeclContext) - dumpDeclContext(cast<DeclContext>(D)); + for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); I != E; + ++I) + dumpAttr(*I); + + if (const FullComment *Comment = + D->getASTContext().getLocalCommentForDeclUncached(D)) + dumpFullComment(Comment); + + // Decls within functions are visited by the body. + if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) && + hasNodes(dyn_cast<DeclContext>(D))) + dumpDeclContext(cast<DeclContext>(D)); + }); } void ASTDumper::VisitLabelDecl(const LabelDecl *D) { @@ -878,19 +1046,16 @@ void ASTDumper::VisitRecordDecl(const RecordDecl *D) { void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { dumpName(D); dumpType(D->getType()); - if (const Expr *Init = D->getInitExpr()) { - lastChild(); + if (const Expr *Init = D->getInitExpr()) dumpStmt(Init); - } } void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { dumpName(D); dumpType(D->getType()); - ChildDumper Children(*this); for (auto *Child : D->chain()) - Children.dumpRef(Child); + dumpDeclRef(Child); } void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { @@ -914,73 +1079,39 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - switch (EPI.ExceptionSpecType) { + switch (EPI.ExceptionSpec.Type) { default: break; case EST_Unevaluated: - OS << " noexcept-unevaluated " << EPI.ExceptionSpecDecl; + OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl; break; case EST_Uninstantiated: - OS << " noexcept-uninstantiated " << EPI.ExceptionSpecTemplate; + OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate; break; } } - bool OldMoreChildren = hasMoreChildren(); - const FunctionTemplateSpecializationInfo *FTSI = - D->getTemplateSpecializationInfo(); - bool HasTemplateSpecialization = FTSI; - - bool HasNamedDecls = D->getDeclsInPrototypeScope().begin() != - D->getDeclsInPrototypeScope().end(); - - bool HasFunctionDecls = D->param_begin() != D->param_end(); - - const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D); - bool HasCtorInitializers = C && C->init_begin() != C->init_end(); - - bool HasDeclarationBody = D->doesThisDeclarationHaveABody(); - - setMoreChildren(OldMoreChildren || HasNamedDecls || HasFunctionDecls || - HasCtorInitializers || HasDeclarationBody); - if (HasTemplateSpecialization) { - lastChild(); + if (const FunctionTemplateSpecializationInfo *FTSI = + D->getTemplateSpecializationInfo()) dumpTemplateArgumentList(*FTSI->TemplateArguments); - } - setMoreChildren(OldMoreChildren || HasFunctionDecls || - HasCtorInitializers || HasDeclarationBody); for (ArrayRef<NamedDecl *>::iterator I = D->getDeclsInPrototypeScope().begin(), - E = D->getDeclsInPrototypeScope().end(); I != E; ++I) { - if (I + 1 == E) - lastChild(); + E = D->getDeclsInPrototypeScope().end(); I != E; ++I) dumpDecl(*I); - } - setMoreChildren(OldMoreChildren || HasCtorInitializers || HasDeclarationBody); for (FunctionDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); + I != E; ++I) dumpDecl(*I); - } - - setMoreChildren(OldMoreChildren || HasDeclarationBody); - if (HasCtorInitializers) + + if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D)) for (CXXConstructorDecl::init_const_iterator I = C->init_begin(), E = C->init_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); + I != E; ++I) dumpCXXCtorInitializer(*I); - } - setMoreChildren(OldMoreChildren); - if (HasDeclarationBody) { - lastChild(); + if (D->doesThisDeclarationHaveABody()) dumpStmt(D->getBody()); - } } void ASTDumper::VisitFieldDecl(const FieldDecl *D) { @@ -991,21 +1122,10 @@ void ASTDumper::VisitFieldDecl(const FieldDecl *D) { if (D->isModulePrivate()) OS << " __module_private__"; - bool OldMoreChildren = hasMoreChildren(); - bool IsBitField = D->isBitField(); - Expr *Init = D->getInClassInitializer(); - bool HasInit = Init; - - setMoreChildren(OldMoreChildren || HasInit); - if (IsBitField) { - lastChild(); + if (D->isBitField()) dumpStmt(D->getBitWidth()); - } - setMoreChildren(OldMoreChildren); - if (HasInit) { - lastChild(); + if (Expr *Init = D->getInClassInitializer()) dumpStmt(Init); - } } void ASTDumper::VisitVarDecl(const VarDecl *D) { @@ -1029,13 +1149,11 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) { case VarDecl::CallInit: OS << " callinit"; break; case VarDecl::ListInit: OS << " listinit"; break; } - lastChild(); dumpStmt(D->getInit()); } } void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { - lastChild(); dumpStmt(D->getAsmString()); } @@ -1082,25 +1200,24 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { return; for (const auto &I : D->bases()) { - IndentScope Indent(*this); - if (I.isVirtual()) - OS << "virtual "; - dumpAccessSpecifier(I.getAccessSpecifier()); - dumpType(I.getType()); - if (I.isPackExpansion()) - OS << "..."; + dumpChild([=] { + if (I.isVirtual()) + OS << "virtual "; + dumpAccessSpecifier(I.getAccessSpecifier()); + dumpType(I.getType()); + if (I.isPackExpansion()) + OS << "..."; + }); } } void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) { dumpStmt(D->getAssertExpr()); - lastChild(); dumpStmt(D->getMessage()); } template<typename SpecializationDecl> -void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children, - const SpecializationDecl *D, +void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D, bool DumpExplicitInst, bool DumpRefOnly) { bool DumpedAny = false; @@ -1125,7 +1242,10 @@ void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children, // Fall through. case TSK_Undeclared: case TSK_ImplicitInstantiation: - Children.dump(Redecl, DumpRefOnly); + if (DumpRefOnly) + dumpDeclRef(Redecl); + else + dumpDecl(Redecl); DumpedAny = true; break; case TSK_ExplicitSpecialization: @@ -1135,7 +1255,7 @@ void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children, // Ensure we dump at least one decl for each specialization. if (!DumpedAny) - Children.dumpRef(D); + dumpDeclRef(D); } template<typename TemplateDecl> @@ -1144,11 +1264,10 @@ void ASTDumper::VisitTemplateDecl(const TemplateDecl *D, dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); - ChildDumper Children(*this); - Children.dump(D->getTemplatedDecl()); + dumpDecl(D->getTemplatedDecl()); for (auto *Child : D->specializations()) - VisitTemplateDeclSpecialization(Children, Child, DumpExplicitInst, + VisitTemplateDeclSpecialization(Child, DumpExplicitInst, !D->isCanonicalDecl()); } @@ -1206,10 +1325,8 @@ void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { if (D->isParameterPack()) OS << " ..."; dumpName(D); - if (D->hasDefaultArgument()) { - lastChild(); + if (D->hasDefaultArgument()) dumpTemplateArgument(D->getDefaultArgument()); - } } void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { @@ -1217,10 +1334,8 @@ void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { if (D->isParameterPack()) OS << " ..."; dumpName(D); - if (D->hasDefaultArgument()) { - lastChild(); + if (D->hasDefaultArgument()) dumpTemplateArgument(D->getDefaultArgument()); - } } void ASTDumper::VisitTemplateTemplateParmDecl( @@ -1229,10 +1344,8 @@ void ASTDumper::VisitTemplateTemplateParmDecl( OS << " ..."; dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); - if (D->hasDefaultArgument()) { - lastChild(); + if (D->hasDefaultArgument()) dumpTemplateArgumentLoc(D->getDefaultArgument()); - } } void ASTDumper::VisitUsingDecl(const UsingDecl *D) { @@ -1273,7 +1386,6 @@ void ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) { } void ASTDumper::VisitFriendDecl(const FriendDecl *D) { - lastChild(); if (TypeSourceInfo *T = D->getFriendType()) dumpType(T->getType()); else @@ -1317,96 +1429,66 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { dumpName(D); dumpType(D->getReturnType()); - bool OldMoreChildren = hasMoreChildren(); - bool IsVariadic = D->isVariadic(); - bool HasBody = D->hasBody(); - - setMoreChildren(OldMoreChildren || IsVariadic || HasBody); if (D->isThisDeclarationADefinition()) { - lastChild(); dumpDeclContext(D); } else { for (ObjCMethodDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); + I != E; ++I) dumpDecl(*I); - } } - setMoreChildren(OldMoreChildren || HasBody); - if (IsVariadic) { - lastChild(); - IndentScope Indent(*this); - OS << "..."; - } + if (D->isVariadic()) + dumpChild([=] { OS << "..."; }); - setMoreChildren(OldMoreChildren); - if (HasBody) { - lastChild(); + if (D->hasBody()) dumpStmt(D->getBody()); - } } void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { dumpName(D); dumpDeclRef(D->getClassInterface()); - if (D->protocol_begin() == D->protocol_end()) - lastChild(); dumpDeclRef(D->getImplementation()); for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(), E = D->protocol_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); + I != E; ++I) dumpDeclRef(*I); - } } void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { dumpName(D); dumpDeclRef(D->getClassInterface()); - lastChild(); dumpDeclRef(D->getCategoryDecl()); } void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { dumpName(D); - ChildDumper Children(*this); for (auto *Child : D->protocols()) - Children.dumpRef(Child); + dumpDeclRef(Child); } void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { dumpName(D); dumpDeclRef(D->getSuperClass(), "super"); - ChildDumper Children(*this); - Children.dumpRef(D->getImplementation()); + dumpDeclRef(D->getImplementation()); for (auto *Child : D->protocols()) - Children.dumpRef(Child); + dumpDeclRef(Child); } void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { dumpName(D); dumpDeclRef(D->getSuperClass(), "super"); - if (D->init_begin() == D->init_end()) - lastChild(); dumpDeclRef(D->getClassInterface()); for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(), E = D->init_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); + I != E; ++I) dumpCXXCtorInitializer(*I); - } } void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) { dumpName(D); - lastChild(); dumpDeclRef(D->getClassInterface()); } @@ -1441,15 +1523,10 @@ void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { OS << " strong"; if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) OS << " unsafe_unretained"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) { - if (!(Attrs & ObjCPropertyDecl::OBJC_PR_setter)) - lastChild(); + if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) dumpDeclRef(D->getGetterMethodDecl(), "getter"); - } - if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) { - lastChild(); + if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) dumpDeclRef(D->getSetterMethodDecl(), "setter"); - } } } @@ -1460,7 +1537,6 @@ void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { else OS << " dynamic"; dumpDeclRef(D->getPropertyDecl()); - lastChild(); dumpDeclRef(D->getPropertyIvarDecl()); } @@ -1468,30 +1544,27 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) { for (auto I : D->params()) dumpDecl(I); - if (D->isVariadic()) { - IndentScope Indent(*this); - OS << "..."; - } + if (D->isVariadic()) + dumpChild([=]{ OS << "..."; }); + + if (D->capturesCXXThis()) + dumpChild([=]{ OS << "capture this"; }); - if (D->capturesCXXThis()) { - IndentScope Indent(*this); - OS << "capture this"; - } for (const auto &I : D->captures()) { - IndentScope Indent(*this); - OS << "capture"; - if (I.isByRef()) - OS << " byref"; - if (I.isNested()) - OS << " nested"; - if (I.getVariable()) { - OS << ' '; - dumpBareDeclRef(I.getVariable()); - } - if (I.hasCopyExpr()) - dumpStmt(I.getCopyExpr()); + dumpChild([=] { + OS << "capture"; + if (I.isByRef()) + OS << " byref"; + if (I.isNested()) + OS << " nested"; + if (I.getVariable()) { + OS << ' '; + dumpBareDeclRef(I.getVariable()); + } + if (I.hasCopyExpr()) + dumpStmt(I.getCopyExpr()); + }); } - lastChild(); dumpStmt(D->getBody()); } @@ -1500,29 +1573,23 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) { //===----------------------------------------------------------------------===// void ASTDumper::dumpStmt(const Stmt *S) { - IndentScope Indent(*this); + dumpChild([=] { + if (!S) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } - if (!S) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>>"; - return; - } + if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { + VisitDeclStmt(DS); + return; + } - if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { - VisitDeclStmt(DS); - return; - } + ConstStmtVisitor<ASTDumper>::Visit(S); - setMoreChildren(!S->children().empty()); - ConstStmtVisitor<ASTDumper>::Visit(S); - setMoreChildren(false); - for (Stmt::const_child_range CI = S->children(); CI; ++CI) { - Stmt::const_child_range Next = CI; - ++Next; - if (!Next) - lastChild(); - dumpStmt(*CI); - } + for (Stmt::const_child_range CI = S->children(); CI; ++CI) + dumpStmt(*CI); + }); } void ASTDumper::VisitStmt(const Stmt *Node) { @@ -1538,22 +1605,16 @@ void ASTDumper::VisitDeclStmt(const DeclStmt *Node) { VisitStmt(Node); for (DeclStmt::const_decl_iterator I = Node->decl_begin(), E = Node->decl_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); + I != E; ++I) dumpDecl(*I); - } } void ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) { VisitStmt(Node); for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(), E = Node->getAttrs().end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); + I != E; ++I) dumpAttr(*I); - } } void ASTDumper::VisitLabelStmt(const LabelStmt *Node) { @@ -1693,15 +1754,7 @@ void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { VisitExpr(Node); - switch (Node->getIdentType()) { - default: llvm_unreachable("unknown case"); - case PredefinedExpr::Func: OS << " __func__"; break; - case PredefinedExpr::Function: OS << " __FUNCTION__"; break; - case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break; - case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break; - case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; - case PredefinedExpr::FuncSig: OS << " __FUNCSIG__"; break; - } + OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType()); } void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { @@ -1734,12 +1787,10 @@ void ASTDumper::VisitStringLiteral(const StringLiteral *Str) { void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) { VisitExpr(ILE); if (auto *Filler = ILE->getArrayFiller()) { - if (!ILE->getNumInits()) - lastChild(); - IndentScope Indent(*this); - OS << "array filler"; - lastChild(); - dumpStmt(Filler); + dumpChild([=] { + OS << "array filler"; + dumpStmt(Filler); + }); } if (auto *Field = ILE->getInitializedFieldInUnion()) { OS << " field "; @@ -1805,10 +1856,8 @@ void ASTDumper::VisitBlockExpr(const BlockExpr *Node) { void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { VisitExpr(Node); - if (Expr *Source = Node->getSourceExpr()) { - lastChild(); + if (Expr *Source = Node->getSourceExpr()) dumpStmt(Source); - } } // GNU extensions. @@ -2024,27 +2073,24 @@ void ASTDumper::dumpFullComment(const FullComment *C) { } void ASTDumper::dumpComment(const Comment *C) { - IndentScope Indent(*this); - - if (!C) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>>"; - return; - } + dumpChild([=] { + if (!C) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } - { - ColorScope Color(*this, CommentColor); - OS << C->getCommentKindName(); - } - dumpPointer(C); - dumpSourceRange(C->getSourceRange()); - ConstCommentVisitor<ASTDumper>::visit(C); - for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpComment(*I); - } + { + ColorScope Color(*this, CommentColor); + OS << C->getCommentKindName(); + } + dumpPointer(C); + dumpSourceRange(C->getSourceRange()); + ConstCommentVisitor<ASTDumper>::visit(C); + for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); + I != E; ++I) + dumpComment(*I); + }); } void ASTDumper::visitTextComment(const TextComment *C) { @@ -2148,6 +2194,23 @@ void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) { } //===----------------------------------------------------------------------===// +// Type method implementations +//===----------------------------------------------------------------------===// + +void QualType::dump(const char *msg) const { + if (msg) + llvm::errs() << msg << ": "; + dump(); +} + +LLVM_DUMP_METHOD void QualType::dump() const { + ASTDumper Dumper(llvm::errs(), nullptr, nullptr); + Dumper.dumpTypeAsChild(*this); +} + +LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); } + +//===----------------------------------------------------------------------===// // Decl method implementations //===----------------------------------------------------------------------===// @@ -2169,13 +2232,14 @@ LLVM_DUMP_METHOD void DeclContext::dumpLookups() const { dumpLookups(llvm::errs()); } -LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS) const { +LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS, + bool DumpDecls) const { const DeclContext *DC = this; while (!DC->isTranslationUnit()) DC = DC->getParent(); ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager()); - P.dumpLookups(this); + P.dumpLookups(this, DumpDecls); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index b0e0b1d..2442e8e 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -151,6 +151,7 @@ namespace clang { Decl *VisitObjCMethodDecl(ObjCMethodDecl *D); Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D); Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D); + Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D); Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D); @@ -1622,15 +1623,14 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn; ToEPI.TypeQuals = FromEPI.TypeQuals; ToEPI.RefQualifier = FromEPI.RefQualifier; - ToEPI.NumExceptions = ExceptionTypes.size(); - ToEPI.Exceptions = ExceptionTypes.data(); - ToEPI.ConsumedParameters = FromEPI.ConsumedParameters; - ToEPI.ExceptionSpecType = FromEPI.ExceptionSpecType; - ToEPI.NoexceptExpr = Importer.Import(FromEPI.NoexceptExpr); - ToEPI.ExceptionSpecDecl = cast_or_null<FunctionDecl>( - Importer.Import(FromEPI.ExceptionSpecDecl)); - ToEPI.ExceptionSpecTemplate = cast_or_null<FunctionDecl>( - Importer.Import(FromEPI.ExceptionSpecTemplate)); + ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type; + ToEPI.ExceptionSpec.Exceptions = ExceptionTypes; + ToEPI.ExceptionSpec.NoexceptExpr = + Importer.Import(FromEPI.ExceptionSpec.NoexceptExpr); + ToEPI.ExceptionSpec.SourceDecl = cast_or_null<FunctionDecl>( + Importer.Import(FromEPI.ExceptionSpec.SourceDecl)); + ToEPI.ExceptionSpec.SourceTemplate = cast_or_null<FunctionDecl>( + Importer.Import(FromEPI.ExceptionSpec.SourceTemplate)); return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI); } @@ -2093,10 +2093,11 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { } case TemplateArgument::Declaration: { - ValueDecl *FromD = From.getAsDecl(); - if (ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(FromD))) - return TemplateArgument(To, From.isDeclForReferenceParam()); - return TemplateArgument(); + ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl())); + QualType ToType = Importer.Import(From.getParamTypeForDecl()); + if (!To || ToType.isNull()) + return TemplateArgument(); + return TemplateArgument(To, ToType); } case TemplateArgument::NullPtr: { @@ -2253,7 +2254,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { } else { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace)) continue; @@ -2316,7 +2317,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -2396,7 +2397,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { if (!DC->isFunctionOrMethod() && SearchName) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(SearchName, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -2482,7 +2483,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(SearchName, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -2604,7 +2605,7 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -2656,7 +2657,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -2712,8 +2713,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // FunctionDecl that we are importing the FunctionProtoType for. // To avoid an infinite recursion when importing, create the FunctionDecl // with a simplified function type and update it afterwards. - if (FromEPI.ExceptionSpecDecl || FromEPI.ExceptionSpecTemplate || - FromEPI.NoexceptExpr) { + if (FromEPI.ExceptionSpec.SourceDecl || + FromEPI.ExceptionSpec.SourceTemplate || + FromEPI.ExceptionSpec.NoexceptExpr) { FunctionProtoType::ExtProtoInfo DefaultEPI; FromTy = Importer.getFromContext().getFunctionType( FromFPT->getReturnType(), FromFPT->getParamTypes(), DefaultEPI); @@ -2858,7 +2860,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) { // For anonymous fields, match up by index. @@ -2914,7 +2916,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (IndirectFieldDecl *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { @@ -2958,9 +2960,12 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { } IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( - Importer.getToContext(), DC, - Loc, Name.getAsIdentifierInfo(), T, - NamedChain, D->getChainingSize()); + Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, + NamedChain, D->getChainingSize()); + + for (const auto *Attr : D->attrs()) + ToIndirectField->addAttr(Attr->clone(Importer.getToContext())); + ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToIndirectField); @@ -2978,7 +2983,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Determine whether we've already imported this ivar SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->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(), @@ -3033,7 +3038,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; @@ -3203,7 +3208,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { return nullptr; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->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()) @@ -3439,7 +3444,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { ObjCProtocolDecl *MergeWithProtocol = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) continue; @@ -3466,6 +3471,36 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { return ToProto; } +Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); + + SourceLocation ExternLoc = Importer.Import(D->getExternLoc()); + SourceLocation LangLoc = Importer.Import(D->getLocation()); + + bool HasBraces = D->hasBraces(); + + LinkageSpecDecl *ToLinkageSpec = + LinkageSpecDecl::Create(Importer.getToContext(), + DC, + ExternLoc, + LangLoc, + D->getLanguage(), + HasBraces); + + if (HasBraces) { + SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc()); + ToLinkageSpec->setRBraceLoc(RBraceLoc); + } + + ToLinkageSpec->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToLinkageSpec); + + Importer.Imported(D, ToLinkageSpec); + + return ToLinkageSpec; +} + bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { @@ -3585,7 +3620,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Look for an existing interface with the same name. ObjCInterfaceDecl *MergeWithIface = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; @@ -3739,7 +3774,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // Check whether we have already imported this property. SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCPropertyDecl *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) { @@ -3972,7 +4007,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; @@ -4161,7 +4196,7 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { "Variable templates cannot be declared at function scope"); SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; - DC->localUncachedLookup(Name, FoundDecls); + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; @@ -4371,7 +4406,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Importer.Import(E->getQualifierLoc()), Importer.Import(E->getTemplateKeywordLoc()), ToD, - E->refersToEnclosingLocal(), + E->refersToEnclosingVariableOrCapture(), Importer.Import(E->getLocation()), T, E->getValueKind(), FoundD, @@ -4760,6 +4795,13 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { case NestedNameSpecifier::Global: return NestedNameSpecifier::GlobalSpecifier(ToContext); + case NestedNameSpecifier::Super: + if (CXXRecordDecl *RD = + cast<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) { + return NestedNameSpecifier::SuperSpecifier(ToContext, RD); + } + return nullptr; + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { QualType T = Import(QualType(FromNNS->getAsType(), 0u)); @@ -4882,7 +4924,10 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) { FromLoc = FromSM.getSpellingLoc(FromLoc); std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc); SourceManager &ToSM = ToContext.getSourceManager(); - return ToSM.getLocForStartOfFile(Import(Decomposed.first)) + FileID ToFileID = Import(Decomposed.first); + if (ToFileID.isInvalid()) + return SourceLocation(); + return ToSM.getLocForStartOfFile(ToFileID) .getLocWithOffset(Decomposed.second); } @@ -4913,16 +4958,19 @@ FileID ASTImporter::Import(FileID FromID) { // FIXME: We definitely want to re-use the existing MemoryBuffer, rather // than mmap the files several times. const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName()); + if (!Entry) + return FileID(); ToID = ToSM.createFileID(Entry, ToIncludeLoc, FromSLoc.getFile().getFileCharacteristic()); } else { // FIXME: We want to re-use the existing MemoryBuffer! const llvm::MemoryBuffer * FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM); - llvm::MemoryBuffer *ToBuf + std::unique_ptr<llvm::MemoryBuffer> ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), FromBuf->getBufferIdentifier()); - ToID = ToSM.createFileID(ToBuf, FromSLoc.getFile().getFileCharacteristic()); + ToID = ToSM.createFileID(std::move(ToBuf), + FromSLoc.getFile().getFileCharacteristic()); } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp index baa8e48..ec0671c 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp @@ -62,6 +62,53 @@ bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; } +ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1, + ASTNodeKind Kind2) { + if (Kind1.isBaseOf(Kind2)) return Kind2; + if (Kind2.isBaseOf(Kind1)) return Kind1; + return ASTNodeKind(); +} + +ASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1, + ASTNodeKind Kind2) { + NodeKindId Parent = Kind1.KindId; + while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None) { + Parent = AllKindInfo[Parent].ParentId; + } + return ASTNodeKind(Parent); +} + +ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) { + switch (D.getKind()) { +#define DECL(DERIVED, BASE) \ + case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl); +#define ABSTRACT_DECL(D) +#include "clang/AST/DeclNodes.inc" + }; + llvm_unreachable("invalid decl kind"); +} + +ASTNodeKind ASTNodeKind::getFromNode(const Stmt &S) { + switch (S.getStmtClass()) { + case Stmt::NoStmtClass: return NKI_None; +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS); +#define ABSTRACT_STMT(S) +#include "clang/AST/StmtNodes.inc" + } + llvm_unreachable("invalid stmt kind"); +} + +ASTNodeKind ASTNodeKind::getFromNode(const Type &T) { + switch (T.getTypeClass()) { +#define TYPE(Class, Base) \ + case Type::Class: return ASTNodeKind(NKI_##Class##Type); +#define ABSTRACT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + } + llvm_unreachable("invalid type kind"); +} + void DynTypedNode::print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const { if (const TemplateArgument *TA = get<TemplateArgument>()) diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h index 12b929b..8e9e358 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h +++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_CXXABI_H -#define LLVM_CLANG_AST_CXXABI_H +#ifndef LLVM_CLANG_LIB_AST_CXXABI_H +#define LLVM_CLANG_LIB_AST_CXXABI_H #include "clang/AST/Type.h" diff --git a/contrib/llvm/tools/clang/lib/AST/Comment.cpp b/contrib/llvm/tools/clang/lib/AST/Comment.cpp index 4f43346..d05c5de 100644 --- a/contrib/llvm/tools/clang/lib/AST/Comment.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Comment.cpp @@ -157,8 +157,7 @@ void DeclInfo::fill() { case Decl::CXXConversion: { const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); Kind = FunctionKind; - ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), - FD->getNumParams()); + ParamVars = llvm::makeArrayRef(FD->param_begin(), FD->getNumParams()); ReturnType = FD->getReturnType(); unsigned NumLists = FD->getNumTemplateParameterLists(); if (NumLists != 0) { @@ -178,8 +177,7 @@ void DeclInfo::fill() { case Decl::ObjCMethod: { const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); Kind = FunctionKind; - ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(), - MD->param_size()); + ParamVars = llvm::makeArrayRef(MD->param_begin(), MD->param_size()); ReturnType = MD->getReturnType(); IsObjCMethod = true; IsInstanceMethod = MD->isInstanceMethod(); @@ -191,8 +189,7 @@ void DeclInfo::fill() { Kind = FunctionKind; TemplateKind = Template; const FunctionDecl *FD = FTD->getTemplatedDecl(); - ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), - FD->getNumParams()); + ParamVars = llvm::makeArrayRef(FD->param_begin(), FD->getNumParams()); ReturnType = FD->getReturnType(); TemplateParameters = FTD->getTemplateParameters(); break; @@ -278,9 +275,7 @@ void DeclInfo::fill() { // Is this a typedef for a function type? if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { Kind = FunctionKind; - ArrayRef<ParmVarDecl *> Params = FTL.getParams(); - ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), - Params.size()); + ParamVars = FTL.getParams(); ReturnType = FTL.getReturnLoc().getType(); break; } @@ -299,9 +294,7 @@ void DeclInfo::fill() { TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { Kind = FunctionKind; - ArrayRef<ParmVarDecl *> Params = FTL.getParams(); - ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), - Params.size()); + ParamVars = FTL.getParams(); ReturnType = FTL.getReturnLoc().getType(); } break; diff --git a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp index a7b07a4..7378a7c 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp @@ -89,6 +89,10 @@ CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) { // Value-initialize (=zero-initialize in this case) a new CommandInfo. CommandInfo *Info = new (Allocator) CommandInfo(); Info->Name = Name; + // We only have a limited number of bits to encode command IDs in the + // CommandInfo structure, so the ID numbers can potentially wrap around. + assert((NextID < (1 << CommandInfo::NumCommandIDBits)) + && "Too many commands. We have limited bits for the command ID."); Info->ID = NextID++; RegisteredCommands.push_back(Info); diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp index 792a832..06a08bd 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp @@ -362,7 +362,7 @@ void Lexer::lexCommentText(Token &T) { } } - const StringRef CommandName(BufferPtr + 1, Length); + StringRef CommandName(BufferPtr + 1, Length); const CommandInfo *Info = Traits.getCommandInfoOrNULL(CommandName); if (!Info) { @@ -531,7 +531,7 @@ void Lexer::lexVerbatimLineText(Token &T) { // Extract current line. const char *Newline = findNewline(BufferPtr, CommentEnd); - const StringRef Text(BufferPtr, Newline - BufferPtr); + StringRef Text(BufferPtr, Newline - BufferPtr); formTokenWithChars(T, Newline, tok::verbatim_line_text); T.setVerbatimLineText(Text); diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 7448de2..e43c28a 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -29,6 +29,7 @@ #include "clang/Basic/Module.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> @@ -38,6 +39,11 @@ Decl *clang::getPrimaryMergedDecl(Decl *D) { return D->getASTContext().getPrimaryMergedDecl(D); } +// Defined here so that it can be inlined into its direct callers. +bool Decl::isOutOfLine() const { + return !getLexicalDeclContext()->Equals(getDeclContext()); +} + //===----------------------------------------------------------------------===// // NamedDecl Implementation //===----------------------------------------------------------------------===// @@ -613,9 +619,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // Explicitly declared static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) return LinkageInfo(InternalLinkage, DefaultVisibility, false); + } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) { + // - a data member of an anonymous union. + const VarDecl *VD = IFD->getVarDecl(); + assert(VD && "Expected a VarDecl in this IndirectFieldDecl!"); + return getLVForNamespaceScopeDecl(VD, computation); } - // - a data member of an anonymous union. - assert(!isa<IndirectFieldDecl>(D) && "Didn't expect an IndirectFieldDecl!"); assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!"); if (D->isInAnonymousNamespace()) { @@ -811,6 +820,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // Everything not covered here has no linkage. } else { + // FIXME: A typedef declaration has linkage if it gives a type a name for + // linkage purposes. return LinkageInfo::none(); } @@ -994,6 +1005,19 @@ bool NamedDecl::isLinkageValid() const { getCachedLinkage(); } +ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const { + StringRef name = getName(); + if (name.empty()) return SFF_None; + + if (name.front() == 'C') + if (name == "CFStringCreateWithFormat" || + name == "CFStringCreateWithFormatAndArguments" || + name == "CFStringAppendFormat" || + name == "CFStringAppendFormatAndArguments") + return SFF_CFString; + return SFF_None; +} + Linkage NamedDecl::getLinkageInternal() const { // We don't care about visibility here, so ask for the cheapest // possible visibility analysis. @@ -1168,7 +1192,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, } else { const FunctionDecl *FD = cast<FunctionDecl>(OuterD); if (!FD->isInlined() && - FD->getTemplateSpecializationKind() == TSK_Undeclared) + !isTemplateInstantiation(FD->getTemplateSpecializationKind())) return LinkageInfo::none(); LV = getLVForDecl(FD, computation); @@ -2607,7 +2631,7 @@ void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { if (!NewDecls.empty()) { NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; std::copy(NewDecls.begin(), NewDecls.end(), A); - DeclsInPrototypeScope = ArrayRef<NamedDecl *>(A, NewDecls.size()); + DeclsInPrototypeScope = llvm::makeArrayRef(A, NewDecls.size()); // Move declarations introduced in prototype to the function context. for (auto I : NewDecls) { DeclContext *DC = I->getDeclContext(); @@ -3168,8 +3192,11 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BImemmove; case Builtin::BIstrlcpy: + case Builtin::BI__builtin___strlcpy_chk: return Builtin::BIstrlcpy; + case Builtin::BIstrlcat: + case Builtin::BI__builtin___strlcat_chk: return Builtin::BIstrlcat; case Builtin::BI__builtin_memcmp: @@ -3261,7 +3288,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const { unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { assert(isBitField() && "not a bitfield"); - Expr *BitWidth = InitializerOrBitWidth.getPointer(); + Expr *BitWidth = static_cast<Expr *>(InitStorage.getPointer()); return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue(); } @@ -3275,30 +3302,39 @@ unsigned FieldDecl::getFieldIndex() const { unsigned Index = 0; const RecordDecl *RD = getParent(); - for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I, ++Index) - I->getCanonicalDecl()->CachedFieldIndex = Index + 1; + for (auto *Field : RD->fields()) { + Field->getCanonicalDecl()->CachedFieldIndex = Index + 1; + ++Index; + } assert(CachedFieldIndex && "failed to find field in parent"); return CachedFieldIndex - 1; } SourceRange FieldDecl::getSourceRange() const { - if (const Expr *E = InitializerOrBitWidth.getPointer()) - return SourceRange(getInnerLocStart(), E->getLocEnd()); - return DeclaratorDecl::getSourceRange(); -} + switch (InitStorage.getInt()) { + // All three of these cases store an optional Expr*. + case ISK_BitWidthOrNothing: + case ISK_InClassCopyInit: + case ISK_InClassListInit: + if (const Expr *E = static_cast<const Expr *>(InitStorage.getPointer())) + return SourceRange(getInnerLocStart(), E->getLocEnd()); + // FALLTHROUGH -void FieldDecl::setBitWidth(Expr *Width) { - assert(!InitializerOrBitWidth.getPointer() && !hasInClassInitializer() && - "bit width or initializer already set"); - InitializerOrBitWidth.setPointer(Width); + case ISK_CapturedVLAType: + return DeclaratorDecl::getSourceRange(); + } + llvm_unreachable("bad init storage kind"); } -void FieldDecl::setInClassInitializer(Expr *Init) { - assert(!InitializerOrBitWidth.getPointer() && hasInClassInitializer() && - "bit width or initializer already set"); - InitializerOrBitWidth.setPointer(Init); +void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) { + assert((getParent()->isLambda() || getParent()->isCapturedRecord()) && + "capturing type in non-lambda or captured record."); + assert(InitStorage.getInt() == ISK_BitWidthOrNothing && + InitStorage.getPointer() == nullptr && + "bit width, initializer or captured type already set"); + InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType), + ISK_CapturedVLAType); } //===----------------------------------------------------------------------===// @@ -3521,6 +3557,20 @@ bool RecordDecl::isInjectedClassName() const { cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName(); } +bool RecordDecl::isLambda() const { + if (auto RD = dyn_cast<CXXRecordDecl>(this)) + return RD->isLambda(); + return false; +} + +bool RecordDecl::isCapturedRecord() const { + return hasAttr<CapturedRecordAttr>(); +} + +void RecordDecl::setCapturedRecord() { + addAttr(CapturedRecordAttr::CreateImplicit(getASTContext())); +} + RecordDecl::field_iterator RecordDecl::field_begin() const { if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage) LoadFieldsFromExternalStorage(); @@ -3578,6 +3628,64 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { /*FieldsAlreadyLoaded=*/false); } +bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { + ASTContext &Context = getASTContext(); + if (!Context.getLangOpts().Sanitize.has(SanitizerKind::Address) || + !Context.getLangOpts().SanitizeAddressFieldPadding) + return false; + const auto &Blacklist = Context.getSanitizerBlacklist(); + const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this); + // We may be able to relax some of these requirements. + int ReasonToReject = -1; + if (!CXXRD || CXXRD->isExternCContext()) + ReasonToReject = 0; // is not C++. + else if (CXXRD->hasAttr<PackedAttr>()) + ReasonToReject = 1; // is packed. + else if (CXXRD->isUnion()) + ReasonToReject = 2; // is a union. + else if (CXXRD->isTriviallyCopyable()) + ReasonToReject = 3; // is trivially copyable. + else if (CXXRD->hasTrivialDestructor()) + ReasonToReject = 4; // has trivial destructor. + else if (CXXRD->isStandardLayout()) + ReasonToReject = 5; // is standard layout. + else if (Blacklist.isBlacklistedLocation(getLocation(), "field-padding")) + ReasonToReject = 6; // is in a blacklisted file. + else if (Blacklist.isBlacklistedType(getQualifiedNameAsString(), + "field-padding")) + ReasonToReject = 7; // is blacklisted. + + if (EmitRemark) { + if (ReasonToReject >= 0) + Context.getDiagnostics().Report( + getLocation(), + diag::remark_sanitize_address_insert_extra_padding_rejected) + << getQualifiedNameAsString() << ReasonToReject; + else + Context.getDiagnostics().Report( + getLocation(), + diag::remark_sanitize_address_insert_extra_padding_accepted) + << getQualifiedNameAsString(); + } + return ReasonToReject < 0; +} + +const FieldDecl *RecordDecl::findFirstNamedDataMember() const { + for (const auto *I : fields()) { + if (I->getIdentifier()) + return I; + + if (const RecordType *RT = I->getType()->getAs<RecordType>()) + if (const FieldDecl *NamedDataMember = + RT->getDecl()->findFirstNamedDataMember()) + return NamedDataMember; + } + + // We didn't find a named data member. + return nullptr; +} + + //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// @@ -3657,6 +3765,13 @@ LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation()); } +void LabelDecl::setMSAsmLabel(StringRef Name) { + char *Buffer = new (getASTContext(), 1) char[Name.size() + 1]; + memcpy(Buffer, Name.data(), Name.size()); + Buffer[Name.size()] = '\0'; + MSAsmName = Buffer; +} + void ValueDecl::anchor() { } bool ValueDecl::isWeak() const { @@ -3892,8 +4007,8 @@ ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const { const SourceLocation *StoredLocs = reinterpret_cast<const SourceLocation *>(this + 1); - return ArrayRef<SourceLocation>(StoredLocs, - getNumModuleIdentifiers(getImportedModule())); + return llvm::makeArrayRef(StoredLocs, + getNumModuleIdentifiers(getImportedModule())); } SourceRange ImportDecl::getSourceRange() const { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 2b1506d..a46787f 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -374,8 +374,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); + VersionTuple VTI(A->getIntroduced()); + VTI.UseDotAsSeparator(); Out << "introduced in " << PrettyPlatformName << ' ' - << A->getIntroduced() << HintMessage; + << VTI << HintMessage; } return AR_NotYetIntroduced; @@ -386,8 +388,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); + VersionTuple VTO(A->getObsoleted()); + VTO.UseDotAsSeparator(); Out << "obsoleted in " << PrettyPlatformName << ' ' - << A->getObsoleted() << HintMessage; + << VTO << HintMessage; } return AR_Unavailable; @@ -398,8 +402,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); + VersionTuple VTD(A->getDeprecated()); + VTD.UseDotAsSeparator(); Out << "first deprecated in " << PrettyPlatformName << ' ' - << A->getDeprecated() << HintMessage; + << VTD << HintMessage; } return AR_Deprecated; @@ -1296,6 +1302,11 @@ DeclContext::lookup(DeclarationName Name) { if (PrimaryContext != this) return PrimaryContext->lookup(Name); + // If this is a namespace, ensure that any later redeclarations of it have + // been loaded, since they may add names to the result of this lookup. + if (auto *ND = dyn_cast<NamespaceDecl>(this)) + (void)ND->getMostRecentDecl(); + if (hasExternalVisibleStorage()) { if (NeedToReconcileExternalVisibleStorage) reconcileExternalVisibleStorage(); @@ -1430,6 +1441,17 @@ DeclContext *DeclContext::getEnclosingNamespaceContext() { return Ctx->getPrimaryContext(); } +RecordDecl *DeclContext::getOuterLexicalRecordContext() { + // Loop until we find a non-record context. + RecordDecl *OutermostRD = nullptr; + DeclContext *DC = this; + while (DC->isRecord()) { + OutermostRD = cast<RecordDecl>(DC); + DC = DC->getLexicalParent(); + } + return OutermostRD; +} + bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const { // For non-file contexts, this is equivalent to Equals. if (!isFileContext()) diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index ed26c52..a6d9d41 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -209,7 +209,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // Now go through all virtual bases of this base and add them. for (const auto &VBase : BaseClassDecl->vbases()) { // Add this base if it's not already in the list. - if (SeenVBaseTypes.insert(C.getCanonicalType(VBase.getType()))) { + if (SeenVBaseTypes.insert(C.getCanonicalType(VBase.getType())).second) { VBases.push_back(&VBase); // C++11 [class.copy]p8: @@ -225,7 +225,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (Base->isVirtual()) { // Add this base if it's not already in the list. - if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType))) + if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)).second) VBases.push_back(Base); // C++0x [meta.unary.prop] is_empty: @@ -677,17 +677,24 @@ void CXXRecordDecl::addedMember(Decl *D) { // // Automatic Reference Counting: the presence of a member of Objective-C pointer type // that does not explicitly have no lifetime makes the class a non-POD. - // However, we delay setting PlainOldData to false in this case so that - // Sema has a chance to diagnostic causes where the same class will be - // non-POD with Automatic Reference Counting but a POD without ARC. - // In this case, the class will become a non-POD class when we complete - // the definition. ASTContext &Context = getASTContext(); QualType T = Context.getBaseElementType(Field->getType()); if (T->isObjCRetainableType() || T.isObjCGCStrong()) { - if (!Context.getLangOpts().ObjCAutoRefCount || - T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) + if (!Context.getLangOpts().ObjCAutoRefCount) { setHasObjectMember(true); + } else if (T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { + // Objective-C Automatic Reference Counting: + // If a class has a non-static data member of Objective-C pointer + // type (or array thereof), it is a non-POD type and its + // default constructor (if any), copy constructor, move constructor, + // copy assignment operator, move assignment operator, and destructor are + // non-trivial. + setHasObjectMember(true); + struct DefinitionData &Data = data(); + Data.PlainOldData = false; + Data.HasTrivialSpecialMembers = 0; + Data.HasIrrelevantDestructor = false; + } } else if (!T.isCXX98PODType(Context)) data().PlainOldData = false; @@ -720,7 +727,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // brace-or-equal-initializers for non-static data members. // // This rule was removed in C++1y. - if (!getASTContext().getLangOpts().CPlusPlus1y) + if (!getASTContext().getLangOpts().CPlusPlus14) data().Aggregate = false; // C++11 [class]p10: @@ -1254,6 +1261,44 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { llvm_unreachable("Not a class template or member class specialization"); } +const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { + // If it's a class template specialization, find the template or partial + // specialization from which it was instantiated. + if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) { + auto From = TD->getInstantiatedFrom(); + if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) { + while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) { + if (NewCTD->isMemberSpecialization()) + break; + CTD = NewCTD; + } + return CTD->getTemplatedDecl(); + } + if (auto *CTPSD = + From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) { + while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) { + if (NewCTPSD->isMemberSpecialization()) + break; + CTPSD = NewCTPSD; + } + return CTPSD; + } + } + + if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { + if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) { + const CXXRecordDecl *RD = this; + while (auto *NewRD = RD->getInstantiatedFromMemberClass()) + RD = NewRD; + return RD; + } + } + + assert(!isTemplateInstantiation(this->getTemplateSpecializationKind()) && + "couldn't find pattern for class template instantiation"); + return nullptr; +} + CXXDestructorDecl *CXXRecordDecl::getDestructor() const { ASTContext &Context = getASTContext(); QualType ClassType = Context.getTypeDeclType(this); @@ -1277,19 +1322,6 @@ void CXXRecordDecl::completeDefinition() { void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { RecordDecl::completeDefinition(); - if (hasObjectMember() && getASTContext().getLangOpts().ObjCAutoRefCount) { - // Objective-C Automatic Reference Counting: - // If a class has a non-static data member of Objective-C pointer - // type (or array thereof), it is a non-POD type and its - // default constructor (if any), copy constructor, move constructor, - // copy assignment operator, move assignment operator, and destructor are - // non-trivial. - struct DefinitionData &Data = data(); - Data.PlainOldData = false; - Data.HasTrivialSpecialMembers = 0; - Data.HasIrrelevantDestructor = false; - } - // If the class may be abstract (but hasn't been marked as such), check for // any pure final overriders. if (mayBeAbstract()) { @@ -1799,7 +1831,6 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { bool CXXConstructorDecl::isSpecializationCopyingObject() const { if ((getNumParams() < 1) || (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || - (getPrimaryTemplate() == nullptr) || (getDescribedFunctionTemplate() != nullptr)) return false; @@ -1970,6 +2001,16 @@ NamespaceDecl *NamespaceDecl::getMostRecentDeclImpl() { void NamespaceAliasDecl::anchor() { } +NamespaceAliasDecl *NamespaceAliasDecl::getNextRedeclarationImpl() { + return getNextRedeclaration(); +} +NamespaceAliasDecl *NamespaceAliasDecl::getPreviousDeclImpl() { + return getPreviousDecl(); +} +NamespaceAliasDecl *NamespaceAliasDecl::getMostRecentDeclImpl() { + return getMostRecentDecl(); +} + NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation AliasLoc, @@ -1977,15 +2018,16 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Namespace) { + // FIXME: Preserve the aliased namespace as written. if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace)) Namespace = NS->getOriginalNamespace(); - return new (C, DC) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, + return new (C, DC) NamespaceAliasDecl(C, DC, UsingLoc, AliasLoc, Alias, QualifierLoc, IdentLoc, Namespace); } NamespaceAliasDecl * NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) NamespaceAliasDecl(nullptr, SourceLocation(), + return new (C, ID) NamespaceAliasDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, NestedNameSpecifierLoc(), SourceLocation(), nullptr); diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index 2204dff..ed53675 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -93,13 +93,13 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, return nullptr; } -/// HasUserDeclaredSetterMethod - This routine returns 'true' if a user declared setter -/// method was found in the class, its protocols, its super classes or categories. -/// It also returns 'true' if one of its categories has declared a 'readwrite' property. -/// This is because, user must provide a setter method for the category's 'readwrite' -/// property. -bool -ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) const { +/// \brief This routine returns 'true' if a user declared setter method was +/// found in the class, its protocols, its super classes or categories. +/// It also returns 'true' if one of its categories has declared a 'readwrite' +/// property. This is because, user must provide a setter method for the +/// category's 'readwrite' property. +bool ObjCContainerDecl::HasUserDeclaredSetterMethod( + const ObjCPropertyDecl *Property) const { Selector Sel = Property->getSetterName(); lookup_const_result R = lookup(Sel); for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end(); @@ -118,9 +118,10 @@ ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) return true; if (Cat->IsClassExtension()) continue; - // Also search through the categories looking for a 'readwrite' declaration - // of this property. If one found, presumably a setter will be provided - // (properties declared in categories will not get auto-synthesized). + // Also search through the categories looking for a 'readwrite' + // declaration of this property. If one found, presumably a setter will + // be provided (properties declared in categories will not get + // auto-synthesized). for (const auto *P : Cat->properties()) if (P->getIdentifier() == Property->getIdentifier()) { if (P->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) @@ -151,7 +152,7 @@ ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) ObjCPropertyDecl * ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, - IdentifierInfo *propertyID) { + const IdentifierInfo *propertyID) { // If this context is a hidden protocol definition, don't find any // property. if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) { @@ -181,8 +182,8 @@ ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const { /// FindPropertyDeclaration - Finds declaration of the property given its name /// in 'PropertyId' and returns it. It returns 0, if not found. -ObjCPropertyDecl * -ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { +ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( + const IdentifierInfo *PropertyId) const { // Don't find properties within hidden protocol definitions. if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) { if (const ObjCProtocolDecl *Def = Proto->getDefinition()) @@ -558,36 +559,39 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, LoadExternalDefinition(); while (ClassDecl) { + // 1. Look through primary class. if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) return MethodDecl; - - // Didn't find one yet - look through protocols. - for (const auto *I : ClassDecl->protocols()) - if ((MethodDecl = I->lookupMethod(Sel, isInstance))) - return MethodDecl; - // Didn't find one yet - now look through categories. - for (const auto *Cat : ClassDecl->visible_categories()) { + // 2. Didn't find one yet - now look through categories. + for (const auto *Cat : ClassDecl->visible_categories()) if ((MethodDecl = Cat->getMethod(Sel, isInstance))) if (C != Cat || !MethodDecl->isImplicit()) return MethodDecl; - if (!shallowCategoryLookup) { + // 3. Didn't find one yet - look through primary class's protocols. + for (const auto *I : ClassDecl->protocols()) + if ((MethodDecl = I->lookupMethod(Sel, isInstance))) + return MethodDecl; + + // 4. Didn't find one yet - now look through categories' protocols + if (!shallowCategoryLookup) + for (const auto *Cat : ClassDecl->visible_categories()) { // Didn't find one yet - look through protocols. const ObjCList<ObjCProtocolDecl> &Protocols = - Cat->getReferencedProtocols(); + Cat->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) if (C != Cat || !MethodDecl->isImplicit()) return MethodDecl; } - } - + + if (!followSuper) return nullptr; - // Get the super class (if any). + // 5. Get to the super class (if any). ClassDecl = ClassDecl->getSuperClass(); } return nullptr; @@ -849,6 +853,11 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { family = OMF_None; break; + case OMF_initialize: + if (isInstanceMethod() || !getReturnType()->isVoidType()) + family = OMF_None; + break; + case OMF_performSelector: if (!isInstanceMethod() || !getReturnType()->isObjCIdType()) family = OMF_None; @@ -952,6 +961,13 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { llvm_unreachable("unknown method context"); } +SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const { + const auto *TSI = getReturnTypeSourceInfo(); + if (TSI) + return TSI->getTypeLoc().getSourceRange(); + return SourceRange(); +} + static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, const ObjCMethodDecl *Method, SmallVectorImpl<const ObjCMethodDecl *> &Methods, diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index e5e5130..c0f3e17 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -87,6 +87,7 @@ namespace { void PrintTemplateParameters(const TemplateParameterList *Params, const TemplateArgumentList *Args = nullptr); void prettyPrintAttributes(Decl *D); + void printDeclType(QualType T, StringRef DeclName, bool Pack = false); }; } @@ -197,6 +198,17 @@ void DeclPrinter::prettyPrintAttributes(Decl *D) { } } +void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) { + // Normally, a PackExpansionType is written as T[3]... (for instance, as a + // template argument), but if it is the type of a declaration, the ellipsis + // is placed before the name being declared. + if (auto *PET = T->getAs<PackExpansionType>()) { + Pack = true; + T = PET->getPattern(); + } + T.print(Out, Policy, (Pack ? "..." : "") + DeclName); +} + void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) { this->Indent(); Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); @@ -365,6 +377,9 @@ void DeclPrinter::VisitRecordDecl(RecordDecl *D) { if (!Policy.SuppressSpecifiers && D->isModulePrivate()) Out << "__module_private__ "; Out << D->getKindName(); + + prettyPrintAttributes(D); + if (D->getIdentifier()) Out << ' ' << *D; @@ -647,7 +662,6 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) { Out << *D << ":"; } - void DeclPrinter::VisitVarDecl(VarDecl *D) { if (!Policy.SuppressSpecifiers) { StorageClass SC = D->getStorageClass(); @@ -675,7 +689,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { QualType T = D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType() : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); - T.print(Out, Policy, D->getName()); + printDeclType(T, D->getName()); Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { bool ImplicitInit = false; @@ -757,6 +771,9 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { if (!Policy.SuppressSpecifiers && D->isModulePrivate()) Out << "__module_private__ "; Out << D->getKindName(); + + prettyPrintAttributes(D); + if (D->getIdentifier()) Out << ' ' << *D; @@ -773,9 +790,11 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { Out << "virtual "; AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); - if (AS != AS_none) + if (AS != AS_none) { Print(AS); - Out << " " << Base->getType().getAsString(Policy); + Out << " "; + } + Out << Base->getType().getAsString(Policy); if (Base->isPackExpansion()) Out << "..."; @@ -830,7 +849,7 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, Out << "class "; if (TTP->isParameterPack()) - Out << "... "; + Out << "..."; Out << *TTP; @@ -843,15 +862,10 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, }; } else if (const NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - Out << NTTP->getType().getAsString(Policy); - - if (NTTP->isParameterPack() && !isa<PackExpansionType>(NTTP->getType())) - Out << "..."; - - if (IdentifierInfo *Name = NTTP->getIdentifier()) { - Out << ' '; - Out << Name->getName(); - } + StringRef Name; + if (IdentifierInfo *II = NTTP->getIdentifier()) + Name = II->getName(); + printDeclType(NTTP->getType(), Name, NTTP->isParameterPack()); if (Args) { Out << " = "; @@ -940,11 +954,12 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { if (OMD->isVariadic()) Out << ", ..."; + + prettyPrintAttributes(OMD); if (OMD->getBody() && !Policy.TerseOutput) { Out << ' '; OMD->getBody()->printPretty(Out, nullptr, Policy); - Out << '\n'; } else if (Policy.PolishForDeclaration) Out << ';'; @@ -954,6 +969,7 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { std::string I = OID->getNameAsString(); ObjCInterfaceDecl *SID = OID->getSuperClass(); + bool eolnOut = false; if (SID) Out << "@implementation " << I << " : " << *SID; else @@ -961,6 +977,7 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { if (OID->ivar_size() > 0) { Out << "{\n"; + eolnOut = true; Indentation += Policy.Indentation; for (const auto *I : OID->ivars()) { Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). @@ -969,7 +986,13 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { Indentation -= Policy.Indentation; Out << "}\n"; } + else if (SID || (OID->decls_begin() != OID->decls_end())) { + Out << "\n"; + eolnOut = true; + } VisitDeclContext(OID, false); + if (!eolnOut) + Out << "\n"; Out << "@end"; } @@ -1008,14 +1031,14 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { Indentation -= Policy.Indentation; Out << "}\n"; } - else if (SID) { + else if (SID || (OID->decls_begin() != OID->decls_end())) { Out << "\n"; eolnOut = true; } VisitDeclContext(OID, false); if (!eolnOut) - Out << ' '; + Out << "\n"; Out << "@end"; // FIXME: implement the rest... } diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 5f559b7..712de50 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -195,12 +195,12 @@ SourceLocation Expr::getExprLoc() const { case Stmt::NoStmtClass: llvm_unreachable("statement without class"); #define ABSTRACT_STMT(type) #define STMT(type, base) \ - case Stmt::type##Class: llvm_unreachable(#type " is not an Expr"); break; + case Stmt::type##Class: break; #define EXPR(type, base) \ case Stmt::type##Class: return getExprLocImpl<type>(this, &type::getExprLoc); #include "clang/AST/StmtNodes.inc" } - llvm_unreachable("unknown statement kind"); + llvm_unreachable("unknown expression kind"); } //===----------------------------------------------------------------------===// @@ -221,11 +221,11 @@ static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D, // (TD) C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: // - // and + // and // // (VD) C++ [temp.dep.constexpr]p2: // An identifier is value-dependent if it is: - + // (TD) - an identifier that was declared with dependent type // (VD) - a name declared with a dependent type, if (T->isDependentType()) { @@ -309,29 +309,11 @@ void DeclRefExpr::computeDependence(const ASTContext &Ctx) { bool InstantiationDependent = false; computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent, ValueDependent, InstantiationDependent); - - // (TD) C++ [temp.dep.expr]p3: - // An id-expression is type-dependent if it contains: - // - // and - // - // (VD) C++ [temp.dep.constexpr]p2: - // An identifier is value-dependent if it is: - if (!TypeDependent && !ValueDependent && - hasExplicitTemplateArgs() && - TemplateSpecializationType::anyDependentTemplateArguments( - getTemplateArgs(), - getNumTemplateArgs(), - InstantiationDependent)) { - TypeDependent = true; - ValueDependent = true; - InstantiationDependent = true; - } - - ExprBits.TypeDependent = TypeDependent; - ExprBits.ValueDependent = ValueDependent; - ExprBits.InstantiationDependent = InstantiationDependent; - + + ExprBits.TypeDependent |= TypeDependent; + ExprBits.ValueDependent |= ValueDependent; + ExprBits.InstantiationDependent |= InstantiationDependent; + // Is the declaration a parameter pack? if (getDecl()->isParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; @@ -340,7 +322,7 @@ void DeclRefExpr::computeDependence(const ASTContext &Ctx) { DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - ValueDecl *D, bool RefersToEnclosingLocal, + ValueDecl *D, bool RefersToEnclosingVariableOrCapture, const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, @@ -348,14 +330,21 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) { DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; - if (QualifierLoc) + if (QualifierLoc) { getInternalQualifierLoc() = QualifierLoc; + auto *NNS = QualifierLoc.getNestedNameSpecifier(); + if (NNS->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (NNS->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + } DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0; if (FoundD) getInternalFoundDecl() = FoundD; DeclRefExprBits.HasTemplateKWAndArgsInfo = (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0; - DeclRefExprBits.RefersToEnclosingLocal = RefersToEnclosingLocal; + DeclRefExprBits.RefersToEnclosingVariableOrCapture = + RefersToEnclosingVariableOrCapture; if (TemplateArgs) { bool Dependent = false; bool InstantiationDependent = false; @@ -364,8 +353,9 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); - if (InstantiationDependent) - setInstantiationDependent(true); + assert(!Dependent && "built a DeclRefExpr with dependent template args"); + ExprBits.InstantiationDependent |= InstantiationDependent; + ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack; } else if (TemplateKWLoc.isValid()) { getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); } @@ -378,14 +368,14 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, - bool RefersToEnclosingLocal, + bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) { return Create(Context, QualifierLoc, TemplateKWLoc, D, - RefersToEnclosingLocal, + RefersToEnclosingVariableOrCapture, DeclarationNameInfo(D->getDeclName(), NameLoc), T, VK, FoundD, TemplateArgs); } @@ -394,7 +384,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, - bool RefersToEnclosingLocal, + bool RefersToEnclosingVariableOrCapture, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, @@ -416,7 +406,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, - RefersToEnclosingLocal, + RefersToEnclosingVariableOrCapture, NameInfo, FoundD, TemplateArgs, T, VK); } @@ -448,6 +438,38 @@ SourceLocation DeclRefExpr::getLocEnd() const { return getNameInfo().getLocEnd(); } +PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, + StringLiteral *SL) + : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary, + FNTy->isDependentType(), FNTy->isDependentType(), + FNTy->isInstantiationDependentType(), + /*ContainsUnexpandedParameterPack=*/false), + Loc(L), Type(IT), FnName(SL) {} + +StringLiteral *PredefinedExpr::getFunctionName() { + return cast_or_null<StringLiteral>(FnName); +} + +StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) { + switch (IT) { + case Func: + return "__func__"; + case Function: + return "__FUNCTION__"; + case FuncDName: + return "__FUNCDNAME__"; + case LFunction: + return "L__FUNCTION__"; + case PrettyFunction: + return "__PRETTY_FUNCTION__"; + case FuncSig: + return "__FUNCSIG__"; + case PrettyFunctionNoVirtual: + break; + } + llvm_unreachable("Unknown ident type for PredefinedExpr"); +} + // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { @@ -477,6 +499,22 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { } return ""; } + if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) { + std::unique_ptr<MangleContext> MC; + MC.reset(Context.createMangleContext()); + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + auto DC = CurrentDecl->getDeclContext(); + if (DC->isFileContext()) + MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out); + else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) + MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); + else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) + MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); + else + MC->mangleBlock(DC, BD, Out); + return Out.str(); + } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) { if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig) return FD->getNameAsString(); @@ -509,6 +547,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { case CC_X86StdCall: POut << "__stdcall "; break; case CC_X86FastCall: POut << "__fastcall "; break; case CC_X86ThisCall: POut << "__thiscall "; break; + case CC_X86VectorCall: POut << "__vectorcall "; break; // Only bother printing the conventions that MSVC knows about. default: break; } @@ -600,9 +639,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { // type deduction and lambdas. For trailing return types resolve the // decltype expression. Otherwise print the real type when this is // not a constructor or destructor. - if ((isa<CXXMethodDecl>(FD) && - cast<CXXMethodDecl>(FD)->getParent()->isLambda()) || - (FT && FT->getReturnType()->getAs<AutoType>())) + if (isa<CXXMethodDecl>(FD) && + cast<CXXMethodDecl>(FD)->getParent()->isLambda()) Proto = "auto " + Proto; else if (FT && FT->getReturnType()->getAs<DecltypeType>()) FT->getReturnType() @@ -1252,7 +1290,7 @@ SourceLocation CallExpr::getLocStart() const { return cast<CXXOperatorCallExpr>(this)->getLocStart(); SourceLocation begin = getCallee()->getLocStart(); - if (begin.isInvalid() && getNumArgs() > 0) + if (begin.isInvalid() && getNumArgs() > 0 && getArg(0)) begin = getArg(0)->getLocStart(); return begin; } @@ -1261,7 +1299,7 @@ SourceLocation CallExpr::getLocEnd() const { return cast<CXXOperatorCallExpr>(this)->getLocEnd(); SourceLocation end = getRParenLoc(); - if (end.isInvalid() && getNumArgs() > 0) + if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1)) end = getArg(getNumArgs() - 1)->getLocEnd(); return end; } @@ -2734,10 +2772,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, if (ILE->getType()->isRecordType()) { unsigned ElementNo = 0; RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl(); - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { + for (const auto *Field : RD->fields()) { // If this is a union, skip all the fields that aren't being initialized. - if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field) + if (RD->isUnion() && ILE->getInitializedFieldInUnion() != Field) continue; // Don't emit anonymous bitfields, they just affect layout. @@ -2830,9 +2867,16 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, return false; } -bool Expr::HasSideEffects(const ASTContext &Ctx) const { +bool Expr::HasSideEffects(const ASTContext &Ctx, + bool IncludePossibleEffects) const { + // In circumstances where we care about definite side effects instead of + // potential side effects, we want to ignore expressions that are part of a + // macro expansion as a potential side effect. + if (!IncludePossibleEffects && getExprLoc().isMacroID()) + return false; + if (isInstantiationDependent()) - return true; + return IncludePossibleEffects; switch (getStmtClass()) { case NoStmtClass: @@ -2850,6 +2894,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case PackExpansionExprClass: case SubstNonTypeTemplateParmPackExprClass: case FunctionParmPackExprClass: + case TypoExprClass: + case CXXFoldExprClass: llvm_unreachable("shouldn't see dependent / unresolved nodes here"); case DeclRefExprClass: @@ -2883,21 +2929,27 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { return false; case CallExprClass: + case CXXOperatorCallExprClass: + case CXXMemberCallExprClass: + case CUDAKernelCallExprClass: + case BlockExprClass: + case CXXBindTemporaryExprClass: + case UserDefinedLiteralClass: + // We don't know a call definitely has side effects, but we can check the + // call's operands. + if (!IncludePossibleEffects) + break; + return true; + case MSPropertyRefExprClass: case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: case StmtExprClass: - case CXXOperatorCallExprClass: - case CXXMemberCallExprClass: - case UserDefinedLiteralClass: case CXXThrowExprClass: case CXXNewExprClass: case CXXDeleteExprClass: case ExprWithCleanupsClass: - case CXXBindTemporaryExprClass: - case BlockExprClass: - case CUDAKernelCallExprClass: // These always have a side-effect. return true; @@ -2933,25 +2985,29 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case InitListExprClass: // FIXME: The children for an InitListExpr doesn't include the array filler. if (const Expr *E = cast<InitListExpr>(this)->getArrayFiller()) - if (E->HasSideEffects(Ctx)) + if (E->HasSideEffects(Ctx, IncludePossibleEffects)) return true; break; case GenericSelectionExprClass: return cast<GenericSelectionExpr>(this)->getResultExpr()-> - HasSideEffects(Ctx); + HasSideEffects(Ctx, IncludePossibleEffects); case ChooseExprClass: - return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(Ctx); + return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects( + Ctx, IncludePossibleEffects); case CXXDefaultArgExprClass: - return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(Ctx); + return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects( + Ctx, IncludePossibleEffects); - case CXXDefaultInitExprClass: - if (const Expr *E = cast<CXXDefaultInitExpr>(this)->getExpr()) - return E->HasSideEffects(Ctx); + case CXXDefaultInitExprClass: { + const FieldDecl *FD = cast<CXXDefaultInitExpr>(this)->getField(); + if (const Expr *E = FD->getInClassInitializer()) + return E->HasSideEffects(Ctx, IncludePossibleEffects); // If we've not yet parsed the initializer, assume it has side-effects. return true; + } case CXXDynamicCastExprClass: { // A dynamic_cast expression has side-effects if it can throw. @@ -2966,6 +3022,13 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case CXXReinterpretCastExprClass: case CXXConstCastExprClass: case CXXFunctionalCastExprClass: { + // While volatile reads are side-effecting in both C and C++, we treat them + // as having possible (not definite) side-effects. This allows idiomatic + // code to behave without warning, such as sizeof(*v) for a volatile- + // qualified pointer. + if (!IncludePossibleEffects) + break; + const CastExpr *CE = cast<CastExpr>(this); if (CE->getCastKind() == CK_LValueToRValue && CE->getSubExpr()->getType().isVolatileQualified()) @@ -2981,7 +3044,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case CXXConstructExprClass: case CXXTemporaryObjectExprClass: { const CXXConstructExpr *CE = cast<CXXConstructExpr>(this); - if (!CE->getConstructor()->isTrivial()) + if (!CE->getConstructor()->isTrivial() && IncludePossibleEffects) return true; // A trivial constructor does not add any side-effects of its own. Just look // at its arguments. @@ -3009,7 +3072,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { const Expr *Subexpr = *I; if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Subexpr)) Subexpr = OVE->getSourceExpr(); - if (Subexpr->HasSideEffects(Ctx)) + if (Subexpr->HasSideEffects(Ctx, IncludePossibleEffects)) return true; } return false; @@ -3018,22 +3081,24 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case ObjCBoxedExprClass: case ObjCArrayLiteralClass: case ObjCDictionaryLiteralClass: - case ObjCMessageExprClass: case ObjCSelectorExprClass: case ObjCProtocolExprClass: - case ObjCPropertyRefExprClass: case ObjCIsaExprClass: case ObjCIndirectCopyRestoreExprClass: case ObjCSubscriptRefExprClass: case ObjCBridgedCastExprClass: - // FIXME: Classify these cases better. - return true; + case ObjCMessageExprClass: + case ObjCPropertyRefExprClass: + // FIXME: Classify these cases better. + if (IncludePossibleEffects) + return true; + break; } // Recurse to children. for (const_child_range SubStmts = children(); SubStmts; ++SubStmts) if (const Stmt *S = *SubStmts) - if (cast<Expr>(S)->HasSideEffects(Ctx)) + if (cast<Expr>(S)->HasSideEffects(Ctx, IncludePossibleEffects)) return true; return false; @@ -3279,6 +3344,10 @@ FieldDecl *Expr::getSourceBitField() { return BinOp->getRHS()->getSourceBitField(); } + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) + if (UnOp->isPrefix() && UnOp->isIncrementDecrementOp()) + return UnOp->getSubExpr()->getSourceBitField(); + return nullptr; } @@ -3759,7 +3828,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, // Compute type- and value-dependence. Expr *Index = IndexExprs[IndexIdx]; if (Index->isTypeDependent() || Index->isValueDependent()) - ExprBits.ValueDependent = true; + ExprBits.TypeDependent = ExprBits.ValueDependent = true; if (Index->isInstantiationDependent()) ExprBits.InstantiationDependent = true; // Propagate unexpanded parameter packs. @@ -3774,7 +3843,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, Expr *End = IndexExprs[IndexIdx + 1]; if (Start->isTypeDependent() || Start->isValueDependent() || End->isTypeDependent() || End->isValueDependent()) { - ExprBits.ValueDependent = true; + ExprBits.TypeDependent = ExprBits.ValueDependent = true; ExprBits.InstantiationDependent = true; } else if (Start->isInstantiationDependent() || End->isInstantiationDependent()) { diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index 64c21dd..9336166 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -909,16 +909,21 @@ LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit, case LCK_ByRef: assert(Var && "capture must have a variable!"); break; + case LCK_VLAType: + assert(!Var && "VLA type capture cannot have a variable!"); + Bits |= Capture_ByCopy; + break; } DeclAndBits.setInt(Bits); } LambdaCaptureKind LambdaCapture::getCaptureKind() const { Decl *D = DeclAndBits.getPointer(); + bool CapByCopy = DeclAndBits.getInt() & Capture_ByCopy; if (!D) - return LCK_This; + return CapByCopy ? LCK_VLAType : LCK_This; - return (DeclAndBits.getInt() & Capture_ByCopy) ? LCK_ByCopy : LCK_ByRef; + return CapByCopy ? LCK_ByCopy : LCK_ByRef; } LambdaExpr::LambdaExpr(QualType T, @@ -1073,8 +1078,8 @@ LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const { "Capture index out-of-range"); VarDecl **IndexVars = getArrayIndexVars(); unsigned *IndexStarts = getArrayIndexStarts(); - return ArrayRef<VarDecl *>(IndexVars + IndexStarts[Index], - IndexVars + IndexStarts[Index + 1]); + return llvm::makeArrayRef(IndexVars + IndexStarts[Index], + IndexVars + IndexStarts[Index + 1]); } CXXRecordDecl *LambdaExpr::getLambdaClass() const { @@ -1399,7 +1404,8 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { // It can't be dependent: after all, we were actually able to do the // lookup. CXXRecordDecl *Record = nullptr; - if (getQualifier()) { + auto *NNS = getQualifier(); + if (NNS && NNS->getKind() != NestedNameSpecifier::Super) { const Type *T = getQualifier()->getAsType(); assert(T && "qualifier in member expression does not name type"); Record = T->getAsCXXRecordDecl(); diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index d3d2530..933ea97 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -124,10 +124,11 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCPropertyRefExprClass: // C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of... case Expr::CXXTypeidExprClass: - // Unresolved lookups get classified as lvalues. + // Unresolved lookups and uncorrected typos get classified as lvalues. // FIXME: Is this wise? Should they get their own kind? case Expr::UnresolvedLookupExprClass: case Expr::UnresolvedMemberExprClass: + case Expr::TypoExprClass: case Expr::CXXDependentScopeMemberExprClass: case Expr::DependentScopeDeclRefExprClass: // ObjC instance variables are lvalues @@ -181,6 +182,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::AtomicExprClass: + case Expr::CXXFoldExprClass: return Cl::CL_PRValue; // Next come the complicated cases. @@ -613,14 +615,9 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, return Cl::CM_IncompleteType; // Records with any const fields (recursively) are not modifiable. - if (const RecordType *R = CT->getAs<RecordType>()) { - assert((E->getObjectKind() == OK_ObjCProperty || - !Ctx.getLangOpts().CPlusPlus) && - "C++ struct assignment should be resolved by the " - "copy assignment operator."); + if (const RecordType *R = CT->getAs<RecordType>()) if (R->hasConstFields()) return Cl::CM_ConstQualified; - } return Cl::CM_Modifiable; } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 7d7ca99..3d7f2dc 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -201,6 +201,7 @@ namespace { /// Determine whether this is a one-past-the-end pointer. bool isOnePastTheEnd() const { + assert(!Invalid); if (IsOnePastTheEnd) return true; if (MostDerivedArraySize && @@ -1308,7 +1309,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, } // Does this refer one past the end of some object? - if (Designator.isOnePastTheEnd()) { + if (!Designator.Invalid && Designator.isOnePastTheEnd()) { const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); Info.Diag(Loc, diag::note_constexpr_past_end, 1) << !Designator.Entries.empty() << !!VD << VD; @@ -1328,7 +1329,7 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E, // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. - if (Info.getLangOpts().CPlusPlus1y && This && + if (Info.getLangOpts().CPlusPlus14 && This && Info.EvaluatingDecl == This->getLValueBase()) return true; @@ -1421,6 +1422,17 @@ static bool IsWeakLValue(const LValue &Value) { return Decl && Decl->isWeak(); } +static bool isZeroSized(const LValue &Value) { + const ValueDecl *Decl = GetLValueBaseDecl(Value); + if (Decl && isa<VarDecl>(Decl)) { + QualType Ty = Decl->getType(); + if (Ty->isArrayType()) + return Ty->isIncompleteType() || + Decl->getASTContext().getTypeSize(Ty) == 0; + } + return false; +} + static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) { // A null base expression indicates a null pointer. These are always // evaluatable, and they are false unless the offset is zero. @@ -2020,7 +2032,9 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived, /// Extract the value of a character from a string literal. static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, uint64_t Index) { - // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant + // FIXME: Support ObjCEncodeExpr, MakeStringConstant + if (auto PE = dyn_cast<PredefinedExpr>(Lit)) + Lit = PE->getFunctionName(); const StringLiteral *S = cast<StringLiteral>(Lit); const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(S->getType()); @@ -2079,6 +2093,64 @@ static void expandArray(APValue &Array, unsigned Index) { Array.swap(NewValue); } +/// Determine whether a type would actually be read by an lvalue-to-rvalue +/// conversion. If it's of class type, we may assume that the copy operation +/// is trivial. Note that this is never true for a union type with fields +/// (because the copy always "reads" the active member) and always true for +/// a non-class type. +static bool isReadByLvalueToRvalueConversion(QualType T) { + CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + if (!RD || (RD->isUnion() && !RD->field_empty())) + return true; + if (RD->isEmpty()) + return false; + + for (auto *Field : RD->fields()) + if (isReadByLvalueToRvalueConversion(Field->getType())) + return true; + + for (auto &BaseSpec : RD->bases()) + if (isReadByLvalueToRvalueConversion(BaseSpec.getType())) + return true; + + return false; +} + +/// Diagnose an attempt to read from any unreadable field within the specified +/// type, which might be a class type. +static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E, + QualType T) { + CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + if (!RD) + return false; + + if (!RD->hasMutableFields()) + return false; + + for (auto *Field : RD->fields()) { + // If we're actually going to read this field in some way, then it can't + // be mutable. If we're in a union, then assigning to a mutable field + // (even an empty one) can change the active member, so that's not OK. + // FIXME: Add core issue number for the union case. + if (Field->isMutable() && + (RD->isUnion() || isReadByLvalueToRvalueConversion(Field->getType()))) { + Info.Diag(E, diag::note_constexpr_ltor_mutable, 1) << Field; + Info.Note(Field->getLocation(), diag::note_declared_at); + return true; + } + + if (diagnoseUnreadableFields(Info, E, Field->getType())) + return true; + } + + for (auto &BaseSpec : RD->bases()) + if (diagnoseUnreadableFields(Info, E, BaseSpec.getType())) + return true; + + // All mutable fields were empty, and thus not actually read. + return false; +} + /// Kinds of access we can perform on an object, for diagnostics. enum AccessKinds { AK_Read, @@ -2134,6 +2206,14 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, } if (I == N) { + // If we are reading an object of class type, there may still be more + // things we need to check: if there are any mutable subobjects, we + // cannot perform this read. (This only happens when performing a trivial + // copy or assignment.) + if (ObjType->isRecordType() && handler.AccessKind == AK_Read && + diagnoseUnreadableFields(Info, E, ObjType)) + return handler.failed(); + if (!handler.found(*O, ObjType)) return false; @@ -2490,7 +2570,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, // Unless we're looking at a local variable or argument in a constexpr call, // the variable we're reading must be const. if (!Frame) { - if (Info.getLangOpts().CPlusPlus1y && + if (Info.getLangOpts().CPlusPlus14 && VD == Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()) { // OK, we can read and modify an object if we're in the process of // evaluating its initializer, because its lifetime began in this @@ -2606,7 +2686,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, // // FIXME: Not all local state is mutable. Allow local constant subobjects // to be read here (but take care with 'mutable' fields). - if (Frame && Info.getLangOpts().CPlusPlus1y && + if (Frame && Info.getLangOpts().CPlusPlus14 && (Info.EvalStatus.HasSideEffects || Info.keepEvaluatingAfterFailure())) return CompleteObject(); @@ -2648,10 +2728,10 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, return false; CompleteObject LitObj(&Lit, Base->getType()); return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal); - } else if (isa<StringLiteral>(Base)) { + } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) { // We represent a string literal array as an lvalue pointing at the // corresponding expression, rather than building an array of chars. - // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant + // FIXME: Support ObjCEncodeExpr, MakeStringConstant APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0); CompleteObject StrObj(&Str, Base->getType()); return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal); @@ -2668,7 +2748,7 @@ static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal, if (LVal.Designator.Invalid) return false; - if (!Info.getLangOpts().CPlusPlus1y) { + if (!Info.getLangOpts().CPlusPlus14) { Info.Diag(E); return false; } @@ -2789,7 +2869,7 @@ static bool handleCompoundAssignment( if (LVal.Designator.Invalid) return false; - if (!Info.getLangOpts().CPlusPlus1y) { + if (!Info.getLangOpts().CPlusPlus14) { Info.Diag(E); return false; } @@ -2938,7 +3018,7 @@ static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal, if (LVal.Designator.Invalid) return false; - if (!Info.getLangOpts().CPlusPlus1y) { + if (!Info.getLangOpts().CPlusPlus14) { Info.Diag(E); return false; } @@ -3588,6 +3668,22 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, return false; } +/// Determine if a class has any fields that might need to be copied by a +/// trivial copy or move operation. +static bool hasFields(const CXXRecordDecl *RD) { + if (!RD || RD->isEmpty()) + return false; + for (auto *FD : RD->fields()) { + if (FD->isUnnamedBitfield()) + continue; + return true; + } + for (auto &Base : RD->bases()) + if (hasFields(Base.getType()->getAsCXXRecordDecl())) + return true; + return false; +} + namespace { typedef SmallVector<APValue, 8> ArgVector; } @@ -3626,8 +3722,12 @@ static bool HandleFunctionCall(SourceLocation CallLoc, // For a trivial copy or move assignment, perform an APValue copy. This is // essential for unions, where the operations performed by the assignment // operator cannot be represented as statements. + // + // Skip this for non-union classes with no fields; in that case, the defaulted + // copy/move does not actually read the object. const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee); - if (MD && MD->isDefaulted() && MD->isTrivial()) { + if (MD && MD->isDefaulted() && MD->isTrivial() && + (MD->getParent()->isUnion() || hasFields(MD->getParent()))) { assert(This && (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())); LValue RHS; @@ -3684,11 +3784,18 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, } // For a trivial copy or move constructor, perform an APValue copy. This is - // essential for unions, where the operations performed by the constructor - // cannot be represented by ctor-initializers. + // essential for unions (or classes with anonymous union members), where the + // operations performed by the constructor cannot be represented by + // ctor-initializers. + // + // Skip this for empty non-union classes; we should not perform an + // lvalue-to-rvalue conversion on them because their copy constructor does not + // actually read them. if (Definition->isDefaulted() && ((Definition->isCopyConstructor() && Definition->isTrivial()) || - (Definition->isMoveConstructor() && Definition->isTrivial()))) { + (Definition->isMoveConstructor() && Definition->isTrivial())) && + (Definition->getParent()->isUnion() || + hasFields(Definition->getParent()))) { LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); return handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), @@ -3985,7 +4092,7 @@ public: const FunctionDecl *FD = nullptr; LValue *This = nullptr, ThisVal; - ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); + auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; // Extract function decl and 'this' pointer from the callee. @@ -4148,7 +4255,7 @@ public: return VisitUnaryPostIncDec(UO); } bool VisitUnaryPostIncDec(const UnaryOperator *UO) { - if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) + if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(UO); LValue LVal; @@ -4573,7 +4680,7 @@ bool LValueExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { } bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) { - if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) + if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(UO); if (!this->Visit(UO->getSubExpr())) @@ -4586,7 +4693,7 @@ bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) { bool LValueExprEvaluator::VisitCompoundAssignOperator( const CompoundAssignOperator *CAO) { - if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) + if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(CAO); APValue RHS; @@ -4608,7 +4715,7 @@ bool LValueExprEvaluator::VisitCompoundAssignOperator( } bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { - if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) + if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(E); APValue NewVal; @@ -4733,6 +4840,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: + case CK_AddressSpaceConversion: if (!Visit(SubExpr)) return false; // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are @@ -4818,6 +4926,38 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { return ExprEvaluatorBaseTy::VisitCastExpr(E); } +static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) { + // C++ [expr.alignof]p3: + // When alignof is applied to a reference type, the result is the + // alignment of the referenced type. + if (const ReferenceType *Ref = T->getAs<ReferenceType>()) + T = Ref->getPointeeType(); + + // __alignof is defined to return the preferred alignment. + return Info.Ctx.toCharUnitsFromBits( + Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); +} + +static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { + E = E->IgnoreParens(); + + // The kinds of expressions that we have special-case logic here for + // should be kept up to date with the special checks for those + // expressions in Sema. + + // alignof decl is always accepted, even if it doesn't make sense: we default + // to 1 in those cases. + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + return Info.Ctx.getDeclAlign(DRE->getDecl(), + /*RefAsPointee*/true); + + if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) + return Info.Ctx.getDeclAlign(ME->getMemberDecl(), + /*RefAsPointee*/true); + + return GetAlignOfType(Info, E->getType()); +} + bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (IsStringLiteralCall(E)) return Success(E); @@ -4825,7 +4965,71 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { switch (E->getBuiltinCallee()) { case Builtin::BI__builtin_addressof: return EvaluateLValue(E->getArg(0), Result, Info); + case Builtin::BI__builtin_assume_aligned: { + // We need to be very careful here because: if the pointer does not have the + // asserted alignment, then the behavior is undefined, and undefined + // behavior is non-constant. + if (!EvaluatePointer(E->getArg(0), Result, Info)) + return false; + + LValue OffsetResult(Result); + APSInt Alignment; + if (!EvaluateInteger(E->getArg(1), Alignment, Info)) + return false; + CharUnits Align = CharUnits::fromQuantity(getExtValue(Alignment)); + + if (E->getNumArgs() > 2) { + APSInt Offset; + if (!EvaluateInteger(E->getArg(2), Offset, Info)) + return false; + + int64_t AdditionalOffset = -getExtValue(Offset); + OffsetResult.Offset += CharUnits::fromQuantity(AdditionalOffset); + } + + // If there is a base object, then it must have the correct alignment. + if (OffsetResult.Base) { + CharUnits BaseAlignment; + if (const ValueDecl *VD = + OffsetResult.Base.dyn_cast<const ValueDecl*>()) { + BaseAlignment = Info.Ctx.getDeclAlign(VD); + } else { + BaseAlignment = + GetAlignOfExpr(Info, OffsetResult.Base.get<const Expr*>()); + } + + if (BaseAlignment < Align) { + Result.Designator.setInvalid(); + // FIXME: Quantities here cast to integers because the plural modifier + // does not work on APSInts yet. + CCEDiag(E->getArg(0), + diag::note_constexpr_baa_insufficient_alignment) << 0 + << (int) BaseAlignment.getQuantity() + << (unsigned) getExtValue(Alignment); + return false; + } + } + + // The offset must also have the correct alignment. + if (OffsetResult.Offset.RoundUpToAlignment(Align) != OffsetResult.Offset) { + Result.Designator.setInvalid(); + APSInt Offset(64, false); + Offset = OffsetResult.Offset.getQuantity(); + if (OffsetResult.Base) + CCEDiag(E->getArg(0), + diag::note_constexpr_baa_insufficient_alignment) << 1 + << (int) getExtValue(Offset) << (unsigned) getExtValue(Alignment); + else + CCEDiag(E->getArg(0), + diag::note_constexpr_baa_value_insufficient_alignment) + << Offset << (unsigned) getExtValue(Alignment); + + return false; + } + + return true; + } default: return ExprEvaluatorBaseTy::VisitCallExpr(E); } @@ -5166,7 +5370,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { if (ZeroInit && !ZeroInitialization(E)) return false; - ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); + auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); return HandleConstructorCall(E->getExprLoc(), This, Args, cast<CXXConstructorDecl>(Definition), Info, Result); @@ -5270,6 +5474,9 @@ public: bool VisitCallExpr(const CallExpr *E) { return VisitConstructExpr(E); } + bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) { + return VisitConstructExpr(E); + } }; } // end anonymous namespace @@ -5645,7 +5852,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, return false; } - ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); + auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); return HandleConstructorCall(E->getExprLoc(), Subobject, Args, cast<CXXConstructorDecl>(Definition), Info, *Value); @@ -5786,8 +5993,6 @@ public: bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); private: - CharUnits GetAlignOfExpr(const Expr *E); - CharUnits GetAlignOfType(QualType T); static QualType GetObjectType(APValue::LValueBase B); bool TryEvaluateBuiltinObjectSize(const CallExpr *E); // FIXME: Missing: array subscript of vector, member of vector @@ -5985,8 +6190,20 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) { return false; } - // If we can prove the base is null, lower to zero now. - if (!Base.getLValueBase()) return Success(0, E); + if (!Base.getLValueBase()) { + // It is not possible to determine which objects ptr points to at compile time, + // __builtin_object_size should return (size_t) -1 for type 0 or 1 + // and (size_t) 0 for type 2 or 3. + llvm::APSInt TypeIntVaue; + const Expr *ExprType = E->getArg(1); + if (!ExprType->EvaluateAsInt(TypeIntVaue, Info.Ctx)) + return false; + if (TypeIntVaue == 0 || TypeIntVaue == 1) + return Success(-1, E); + if (TypeIntVaue == 2 || TypeIntVaue == 3) + return Success(0, E); + return Error(E); + } QualType T = GetObjectType(Base.getLValueBase()); if (T.isNull() || @@ -6286,6 +6503,27 @@ static bool HasSameBase(const LValue &A, const LValue &B) { A.getLValueCallIndex() == B.getLValueCallIndex(); } +/// \brief Determine whether this is a pointer past the end of the complete +/// object referred to by the lvalue. +static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx, + const LValue &LV) { + // A null pointer can be viewed as being "past the end" but we don't + // choose to look at it that way here. + if (!LV.getLValueBase()) + return false; + + // If the designator is valid and refers to a subobject, we're not pointing + // past the end. + if (!LV.getLValueDesignator().Invalid && + !LV.getLValueDesignator().isOnePastTheEnd()) + return false; + + // We're a past-the-end pointer if we point to the byte after the object, + // no matter what our type or path is. + auto Size = Ctx.getTypeSizeInChars(getType(LV.getLValueBase())); + return LV.getLValueOffset() == Size; +} + namespace { /// \brief Data recursive integer evaluator of certain binary operators. @@ -6605,15 +6843,27 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { QualType LHSTy = E->getLHS()->getType(); QualType RHSTy = E->getRHS()->getType(); - if (LHSTy->isAnyComplexType()) { - assert(RHSTy->isAnyComplexType() && "Invalid comparison"); + if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) { ComplexValue LHS, RHS; - - bool LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); + bool LHSOK; + if (E->getLHS()->getType()->isRealFloatingType()) { + LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info); + if (LHSOK) { + LHS.makeComplexFloat(); + LHS.FloatImag = APFloat(LHS.FloatReal.getSemantics()); + } + } else { + LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); + } if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; - if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) + if (E->getRHS()->getType()->isRealFloatingType()) { + if (!EvaluateFloat(E->getRHS(), RHS.FloatReal, Info) || !LHSOK) + return false; + RHS.makeComplexFloat(); + RHS.FloatImag = APFloat(RHS.FloatReal.getSemantics()); + } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; if (LHS.isComplexFloat()) { @@ -6736,6 +6986,18 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // object. if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue)) return Error(E); + // We can't compare the address of the start of one object with the + // past-the-end address of another object, per C++ DR1652. + if ((LHSValue.Base && LHSValue.Offset.isZero() && + isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) || + (RHSValue.Base && RHSValue.Offset.isZero() && + isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue))) + return Error(E); + // We can't tell whether an object is at the same address as another + // zero sized object. + if ((RHSValue.Base && isZeroSized(LHSValue)) || + (LHSValue.Base && isZeroSized(RHSValue))) + return Error(E); // Pointers with different bases cannot represent the same object. // (Note that clang defaults to -fmerge-all-constants, which can // lead to inconsistent results for comparisons involving the address @@ -6940,39 +7202,6 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { return ExprEvaluatorBaseTy::VisitBinaryOperator(E); } -CharUnits IntExprEvaluator::GetAlignOfType(QualType T) { - // C++ [expr.alignof]p3: - // When alignof is applied to a reference type, the result is the - // alignment of the referenced type. - if (const ReferenceType *Ref = T->getAs<ReferenceType>()) - T = Ref->getPointeeType(); - - // __alignof is defined to return the preferred alignment. - return Info.Ctx.toCharUnitsFromBits( - Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); -} - -CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) { - E = E->IgnoreParens(); - - // The kinds of expressions that we have special-case logic here for - // should be kept up to date with the special checks for those - // expressions in Sema. - - // alignof decl is always accepted, even if it doesn't make sense: we default - // to 1 in those cases. - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) - return Info.Ctx.getDeclAlign(DRE->getDecl(), - /*RefAsPointee*/true); - - if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) - return Info.Ctx.getDeclAlign(ME->getMemberDecl(), - /*RefAsPointee*/true); - - return GetAlignOfType(E->getType()); -} - - /// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with /// a result as the expression's type. bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( @@ -6980,9 +7209,9 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( switch(E->getKind()) { case UETT_AlignOf: { if (E->isArgumentType()) - return Success(GetAlignOfType(E->getArgumentType()), E); + return Success(GetAlignOfType(Info, E->getArgumentType()), E); else - return Success(GetAlignOfExpr(E->getArgumentExpr()), E); + return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E); } case UETT_VecStep: { @@ -7732,24 +7961,49 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); - bool LHSOK = Visit(E->getLHS()); + // Track whether the LHS or RHS is real at the type system level. When this is + // the case we can simplify our evaluation strategy. + bool LHSReal = false, RHSReal = false; + + bool LHSOK; + if (E->getLHS()->getType()->isRealFloatingType()) { + LHSReal = true; + APFloat &Real = Result.FloatReal; + LHSOK = EvaluateFloat(E->getLHS(), Real, Info); + if (LHSOK) { + Result.makeComplexFloat(); + Result.FloatImag = APFloat(Real.getSemantics()); + } + } else { + LHSOK = Visit(E->getLHS()); + } if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; ComplexValue RHS; - if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) + if (E->getRHS()->getType()->isRealFloatingType()) { + RHSReal = true; + APFloat &Real = RHS.FloatReal; + if (!EvaluateFloat(E->getRHS(), Real, Info) || !LHSOK) + return false; + RHS.makeComplexFloat(); + RHS.FloatImag = APFloat(Real.getSemantics()); + } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; - assert(Result.isComplexFloat() == RHS.isComplexFloat() && - "Invalid operands to binary operator."); + assert(!(LHSReal && RHSReal) && + "Cannot have both operands of a complex operation be real."); switch (E->getOpcode()) { default: return Error(E); case BO_Add: if (Result.isComplexFloat()) { Result.getComplexFloatReal().add(RHS.getComplexFloatReal(), APFloat::rmNearestTiesToEven); - Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), - APFloat::rmNearestTiesToEven); + if (LHSReal) + Result.getComplexFloatImag() = RHS.getComplexFloatImag(); + else if (!RHSReal) + Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), + APFloat::rmNearestTiesToEven); } else { Result.getComplexIntReal() += RHS.getComplexIntReal(); Result.getComplexIntImag() += RHS.getComplexIntImag(); @@ -7759,8 +8013,13 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (Result.isComplexFloat()) { Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(), APFloat::rmNearestTiesToEven); - Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), - APFloat::rmNearestTiesToEven); + if (LHSReal) { + Result.getComplexFloatImag() = RHS.getComplexFloatImag(); + Result.getComplexFloatImag().changeSign(); + } else if (!RHSReal) { + Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), + APFloat::rmNearestTiesToEven); + } } else { Result.getComplexIntReal() -= RHS.getComplexIntReal(); Result.getComplexIntImag() -= RHS.getComplexIntImag(); @@ -7768,25 +8027,75 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { break; case BO_Mul: if (Result.isComplexFloat()) { + // This is an implementation of complex multiplication according to the + // constraints laid out in C11 Annex G. The implemantion uses the + // following naming scheme: + // (a + ib) * (c + id) ComplexValue LHS = Result; - APFloat &LHS_r = LHS.getComplexFloatReal(); - APFloat &LHS_i = LHS.getComplexFloatImag(); - APFloat &RHS_r = RHS.getComplexFloatReal(); - APFloat &RHS_i = RHS.getComplexFloatImag(); - - APFloat Tmp = LHS_r; - Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven); - Result.getComplexFloatReal() = Tmp; - Tmp = LHS_i; - Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); - Result.getComplexFloatReal().subtract(Tmp, APFloat::rmNearestTiesToEven); - - Tmp = LHS_r; - Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); - Result.getComplexFloatImag() = Tmp; - Tmp = LHS_i; - Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven); - Result.getComplexFloatImag().add(Tmp, APFloat::rmNearestTiesToEven); + APFloat &A = LHS.getComplexFloatReal(); + APFloat &B = LHS.getComplexFloatImag(); + APFloat &C = RHS.getComplexFloatReal(); + APFloat &D = RHS.getComplexFloatImag(); + APFloat &ResR = Result.getComplexFloatReal(); + APFloat &ResI = Result.getComplexFloatImag(); + if (LHSReal) { + assert(!RHSReal && "Cannot have two real operands for a complex op!"); + ResR = A * C; + ResI = A * D; + } else if (RHSReal) { + ResR = C * A; + ResI = C * B; + } else { + // In the fully general case, we need to handle NaNs and infinities + // robustly. + APFloat AC = A * C; + APFloat BD = B * D; + APFloat AD = A * D; + APFloat BC = B * C; + ResR = AC - BD; + ResI = AD + BC; + if (ResR.isNaN() && ResI.isNaN()) { + bool Recalc = false; + if (A.isInfinity() || B.isInfinity()) { + A = APFloat::copySign( + APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); + B = APFloat::copySign( + APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); + if (C.isNaN()) + C = APFloat::copySign(APFloat(C.getSemantics()), C); + if (D.isNaN()) + D = APFloat::copySign(APFloat(D.getSemantics()), D); + Recalc = true; + } + if (C.isInfinity() || D.isInfinity()) { + C = APFloat::copySign( + APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); + D = APFloat::copySign( + APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); + if (A.isNaN()) + A = APFloat::copySign(APFloat(A.getSemantics()), A); + if (B.isNaN()) + B = APFloat::copySign(APFloat(B.getSemantics()), B); + Recalc = true; + } + if (!Recalc && (AC.isInfinity() || BD.isInfinity() || + AD.isInfinity() || BC.isInfinity())) { + if (A.isNaN()) + A = APFloat::copySign(APFloat(A.getSemantics()), A); + if (B.isNaN()) + B = APFloat::copySign(APFloat(B.getSemantics()), B); + if (C.isNaN()) + C = APFloat::copySign(APFloat(C.getSemantics()), C); + if (D.isNaN()) + D = APFloat::copySign(APFloat(D.getSemantics()), D); + Recalc = true; + } + if (Recalc) { + ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D); + ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C); + } + } + } } else { ComplexValue LHS = Result; Result.getComplexIntReal() = @@ -7799,33 +8108,57 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { break; case BO_Div: if (Result.isComplexFloat()) { + // This is an implementation of complex division according to the + // constraints laid out in C11 Annex G. The implemantion uses the + // following naming scheme: + // (a + ib) / (c + id) ComplexValue LHS = Result; - APFloat &LHS_r = LHS.getComplexFloatReal(); - APFloat &LHS_i = LHS.getComplexFloatImag(); - APFloat &RHS_r = RHS.getComplexFloatReal(); - APFloat &RHS_i = RHS.getComplexFloatImag(); - APFloat &Res_r = Result.getComplexFloatReal(); - APFloat &Res_i = Result.getComplexFloatImag(); - - APFloat Den = RHS_r; - Den.multiply(RHS_r, APFloat::rmNearestTiesToEven); - APFloat Tmp = RHS_i; - Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); - Den.add(Tmp, APFloat::rmNearestTiesToEven); - - Res_r = LHS_r; - Res_r.multiply(RHS_r, APFloat::rmNearestTiesToEven); - Tmp = LHS_i; - Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); - Res_r.add(Tmp, APFloat::rmNearestTiesToEven); - Res_r.divide(Den, APFloat::rmNearestTiesToEven); - - Res_i = LHS_i; - Res_i.multiply(RHS_r, APFloat::rmNearestTiesToEven); - Tmp = LHS_r; - Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); - Res_i.subtract(Tmp, APFloat::rmNearestTiesToEven); - Res_i.divide(Den, APFloat::rmNearestTiesToEven); + APFloat &A = LHS.getComplexFloatReal(); + APFloat &B = LHS.getComplexFloatImag(); + APFloat &C = RHS.getComplexFloatReal(); + APFloat &D = RHS.getComplexFloatImag(); + APFloat &ResR = Result.getComplexFloatReal(); + APFloat &ResI = Result.getComplexFloatImag(); + if (RHSReal) { + ResR = A / C; + ResI = B / C; + } else { + if (LHSReal) { + // No real optimizations we can do here, stub out with zero. + B = APFloat::getZero(A.getSemantics()); + } + int DenomLogB = 0; + APFloat MaxCD = maxnum(abs(C), abs(D)); + if (MaxCD.isFinite()) { + DenomLogB = ilogb(MaxCD); + C = scalbn(C, -DenomLogB); + D = scalbn(D, -DenomLogB); + } + APFloat Denom = C * C + D * D; + ResR = scalbn((A * C + B * D) / Denom, -DenomLogB); + ResI = scalbn((B * C - A * D) / Denom, -DenomLogB); + if (ResR.isNaN() && ResI.isNaN()) { + if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) { + ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A; + ResI = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * B; + } else if ((A.isInfinity() || B.isInfinity()) && C.isFinite() && + D.isFinite()) { + A = APFloat::copySign( + APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); + B = APFloat::copySign( + APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); + ResR = APFloat::getInf(ResR.getSemantics()) * (A * C + B * D); + ResI = APFloat::getInf(ResI.getSemantics()) * (B * C - A * D); + } else if (MaxCD.isInfinity() && A.isFinite() && B.isFinite()) { + C = APFloat::copySign( + APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); + D = APFloat::copySign( + APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); + ResR = APFloat::getZero(ResR.getSemantics()) * (A * C + B * D); + ResI = APFloat::getZero(ResI.getSemantics()) * (B * C - A * D); + } + } + } } else { if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) return Error(E, diag::note_expr_divide_by_zero); @@ -7966,6 +8299,7 @@ public: default: return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__assume: + case Builtin::BI__builtin_assume: // The argument is not evaluated! return true; } @@ -8338,6 +8672,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::CXXDeleteExprClass: case Expr::CXXPseudoDestructorExprClass: case Expr::UnresolvedLookupExprClass: + case Expr::TypoExprClass: case Expr::DependentScopeDeclRefExprClass: case Expr::CXXConstructExprClass: case Expr::CXXStdInitializerListExprClass: @@ -8373,6 +8708,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: case Expr::LambdaExprClass: + case Expr::CXXFoldExprClass: return ICEDiag(IK_NotICE, E->getLocStart()); case Expr::InitListExprClass: { @@ -8682,7 +9018,11 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc)) return false; - assert(Result.isInt() && "pointer cast to int is not an ICE"); + if (!Result.isInt()) { + if (Loc) *Loc = E->getExprLoc(); + return false; + } + if (Value) *Value = Result.getInt(); return true; } @@ -8751,7 +9091,8 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, ArgVector ArgValues(Args.size()); for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end(); I != E; ++I) { - if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) + if ((*I)->isValueDependent() || + !Evaluate(ArgValues[I - Args.begin()], Info, *I)) // If evaluation fails, throw away the argument entirely. ArgValues[I - Args.begin()] = APValue(); if (Info.EvalStatus.HasSideEffects) diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index b5f8c0f..378121c 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -29,16 +29,64 @@ using namespace clang; namespace { +/// According to Itanium C++ ABI 5.1.2: +/// the name of an anonymous union is considered to be +/// the name of the first named data member found by a pre-order, +/// depth-first, declaration-order walk of the data members of +/// the anonymous union. +/// If there is no such data member (i.e., if all of the data members +/// in the union are unnamed), then there is no way for a program to +/// refer to the anonymous union, and there is therefore no need to mangle its name. +/// +/// Returns the name of anonymous union VarDecl or nullptr if it is not found. +static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) { + const RecordType *RT = VD.getType()->getAs<RecordType>(); + assert(RT && "type of VarDecl is expected to be RecordType."); + assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union."); + if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) { + return FD->getIdentifier(); + } + + return nullptr; +} + /// \brief Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. class ItaniumNumberingContext : public MangleNumberingContext { - llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers; - llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers; + llvm::DenseMap<const Type *, unsigned> ManglingNumbers; + llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers; + llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers; public: + unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { + const FunctionProtoType *Proto = + CallOperator->getType()->getAs<FunctionProtoType>(); + ASTContext &Context = CallOperator->getASTContext(); + + QualType Key = + Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), + FunctionProtoType::ExtProtoInfo()); + Key = Context.getCanonicalType(Key); + return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; + } + + unsigned getManglingNumber(const BlockDecl *BD) override { + const Type *Ty = nullptr; + return ++ManglingNumbers[Ty]; + } + + unsigned getStaticLocalNumber(const VarDecl *VD) override { + return 0; + } + /// Variable decls are numbered by identifier. unsigned getManglingNumber(const VarDecl *VD, unsigned) override { - return ++VarManglingNumbers[VD->getIdentifier()]; + const IdentifierInfo *Identifier = VD->getIdentifier(); + if (!Identifier) { + // VarDecl without an identifier represents an anonymous union declaration. + Identifier = findAnonymousUnionVarDeclName(*VD); + } + return ++VarManglingNumbers[Identifier]; } unsigned getManglingNumber(const TagDecl *TD, unsigned) override { diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 977d6fc..156ad64 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -117,7 +117,7 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy; llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator; llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier; - + public: explicit ItaniumMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) @@ -150,6 +150,8 @@ public: void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, raw_ostream &) override; + void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override; + void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override; void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) override; void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override; void mangleDynamicAtExitDestructor(const VarDecl *D, @@ -373,6 +375,7 @@ private: NamedDecl *firstQualifierLookup, DeclarationName name, unsigned knownArity); + void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleExpression(const Expr *E, unsigned Arity = UnknownArity); void mangleCXXCtorType(CXXCtorType T); void mangleCXXDtorType(CXXDtorType T); @@ -634,13 +637,11 @@ void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) { return; // <template-template-param> ::= <template-param> - if (const TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(ND)) { + if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) mangleTemplateParameter(TTP->getIndex()); - return; - } + else + mangleUnscopedName(ND->getTemplatedDecl()); - mangleUnscopedName(ND->getTemplatedDecl()); addSubstitution(ND); } @@ -811,6 +812,9 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, // We never want an 'E' here. return; + case NestedNameSpecifier::Super: + llvm_unreachable("Can't mangle __super specifier"); + case NestedNameSpecifier::Namespace: if (qualifier->getPrefix()) mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, @@ -1046,24 +1050,6 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, mangleUnqualifiedName(nullptr, name, knownArity); } -static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) { - assert(RD->isAnonymousStructOrUnion() && - "Expected anonymous struct or union!"); - - for (const auto *I : RD->fields()) { - if (I->getIdentifier()) - return I; - - if (const RecordType *RT = I->getType()->getAs<RecordType>()) - if (const FieldDecl *NamedDataMember = - FindFirstNamedDataMember(RT->getDecl())) - return NamedDataMember; - } - - // We didn't find a named data member. - return nullptr; -} - void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, unsigned KnownArity) { @@ -1100,9 +1086,9 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { // We must have an anonymous union or struct declaration. - const RecordDecl *RD = + const RecordDecl *RD = cast<RecordDecl>(VD->getType()->getAs<RecordType>()->getDecl()); - + // Itanium C++ ABI 5.1.2: // // For the purposes of mangling, the name of an anonymous union is @@ -1112,14 +1098,16 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // the data members in the union are unnamed), then there is no way for // a program to refer to the anonymous union, and there is therefore no // need to mangle its name. - const FieldDecl *FD = FindFirstNamedDataMember(RD); + assert(RD->isAnonymousStructOrUnion() + && "Expected anonymous struct or union!"); + const FieldDecl *FD = RD->findFirstNamedDataMember(); // It's actually possible for various reasons for us to get here // with an empty anonymous struct / union. Fortunately, it // doesn't really matter what name we generate. if (!FD) break; assert(FD->getIdentifier() && "Data member name isn't an identifier!"); - + mangleSourceName(FD->getIdentifier()); break; } @@ -1409,8 +1397,8 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { if (!Number) Number = Context.getBlockId(Block, false); Out << "Ub"; - if (Number > 1) - Out << Number - 2; + if (Number > 0) + Out << Number - 1; Out << '_'; } @@ -1459,6 +1447,9 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { // nothing return; + case NestedNameSpecifier::Super: + llvm_unreachable("Can't mangle __super specifier"); + case NestedNameSpecifier::Namespace: mangleName(qualifier->getAsNamespace()); return; @@ -1554,14 +1545,13 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND, return; // <template-template-param> ::= <template-param> - if (const TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(ND)) { + if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) { mangleTemplateParameter(TTP->getIndex()); - return; + } else { + manglePrefix(getEffectiveDeclContext(ND), NoFunction); + mangleUnqualifiedName(ND->getTemplatedDecl()); } - manglePrefix(getEffectiveDeclContext(ND), NoFunction); - mangleUnqualifiedName(ND->getTemplatedDecl()); addSubstitution(ND); } @@ -1834,6 +1824,19 @@ void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { Context.mangleObjCMethodName(MD, Out); } +static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty) { + if (Quals) + return true; + if (Ty->isSpecificBuiltinType(BuiltinType::ObjCSel)) + return true; + if (Ty->isOpenCLSpecificType()) + return true; + if (Ty->isBuiltinType()) + return false; + + return true; +} + void CXXNameMangler::mangleType(QualType T) { // If our type is instantiation-dependent but not dependent, we mangle // it as it was written in the source, removing any top-level sugar. @@ -1875,7 +1878,7 @@ void CXXNameMangler::mangleType(QualType T) { Qualifiers quals = split.Quals; const Type *ty = split.Ty; - bool isSubstitutable = quals || !isa<BuiltinType>(T); + bool isSubstitutable = isTypeSubstitutable(quals, ty); if (isSubstitutable && mangleSubstitution(T)) return; @@ -2301,9 +2304,7 @@ void CXXNameMangler::mangleType(const VectorType *T) { llvm::Triple::ArchType Arch = getASTContext().getTargetInfo().getTriple().getArch(); if ((Arch == llvm::Triple::aarch64 || - Arch == llvm::Triple::aarch64_be || - Arch == llvm::Triple::arm64_be || - Arch == llvm::Triple::arm64) && !Target.isOSDarwin()) + Arch == llvm::Triple::aarch64_be) && !Target.isOSDarwin()) mangleAArch64NeonVectorType(T); else mangleNeonVectorType(T); @@ -2528,6 +2529,18 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base, // <expression> ::= dt <expression> <unresolved-name> // ::= pt <expression> <unresolved-name> if (base) { + + // Ignore member expressions involving anonymous unions. + while (const auto *RT = base->getType()->getAs<RecordType>()) { + if (!RT->getDecl()->isAnonymousStructOrUnion()) + break; + const auto *ME = dyn_cast<MemberExpr>(base); + if (!ME) + break; + base = ME->getBase(); + isArrow = ME->isArrow(); + } + if (base->isImplicitCXXThis()) { // Note: GCC mangles member expressions to the implicit 'this' as // *this., whereas we represent them as this->. The Itanium C++ ABI @@ -2572,12 +2585,23 @@ static bool isParenthesizedADLCallee(const CallExpr *call) { return true; } +void CXXNameMangler::mangleCastExpression(const Expr *E, StringRef CastEncoding) { + const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E); + Out << CastEncoding; + mangleType(ECE->getType()); + mangleExpression(ECE->getSubExpr()); +} + void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { // <expression> ::= <unary operator-name> <expression> // ::= <binary operator-name> <expression> <expression> // ::= <trinary operator-name> <expression> <expression> <expression> // ::= cv <type> expression # conversion with one argument // ::= cv <type> _ <expression>* E # conversion with a different number of arguments + // ::= dc <type> <expression> # dynamic_cast<type> (expression) + // ::= sc <type> <expression> # static_cast<type> (expression) + // ::= cc <type> <expression> # const_cast<type> (expression) + // ::= rc <type> <expression> # reinterpret_cast<type> (expression) // ::= st <type> # sizeof (a type) // ::= at <type> # alignof (a type) // ::= <template-param> @@ -2612,6 +2636,7 @@ recurse: case Expr::ParenListExprClass: case Expr::LambdaExprClass: case Expr::MSPropertyRefExprClass: + case Expr::TypoExprClass: // This should no longer exist in the AST by now. llvm_unreachable("unexpected statement kind"); // FIXME: invent manglings for all these. @@ -2643,7 +2668,6 @@ recurse: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::VAArgExprClass: - case Expr::CXXUuidofExprClass: case Expr::CUDAKernelCallExprClass: case Expr::AsTypeExprClass: case Expr::PseudoObjectExprClass: @@ -2658,6 +2682,20 @@ recurse: break; } + case Expr::CXXUuidofExprClass: { + const CXXUuidofExpr *UE = cast<CXXUuidofExpr>(E); + if (UE->isTypeOperand()) { + QualType UuidT = UE->getTypeOperand(Context.getASTContext()); + Out << "u8__uuidoft"; + mangleType(UuidT); + } else { + Expr *UuidExp = UE->getExprOperand(); + Out << "u8__uuidofz"; + mangleExpression(UuidExp, Arity); + } + break; + } + // Even gcc-4.5 doesn't mangle this. case Expr::BinaryConditionalOperatorClass: { DiagnosticsEngine &Diags = Context.getDiags(); @@ -2982,17 +3020,22 @@ recurse: // Fall through to mangle the cast itself. case Expr::CStyleCastExprClass: + case Expr::CXXFunctionalCastExprClass: + mangleCastExpression(E, "cv"); + break; + case Expr::CXXStaticCastExprClass: + mangleCastExpression(E, "sc"); + break; case Expr::CXXDynamicCastExprClass: + mangleCastExpression(E, "dc"); + break; case Expr::CXXReinterpretCastExprClass: + mangleCastExpression(E, "rc"); + break; case Expr::CXXConstCastExprClass: - case Expr::CXXFunctionalCastExprClass: { - const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E); - Out << "cv"; - mangleType(ECE->getType()); - mangleExpression(ECE->getSubExpr()); + mangleCastExpression(E, "cc"); break; - } case Expr::CXXOperatorCallExprClass: { const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E); @@ -3175,12 +3218,33 @@ recurse: mangleFunctionParam(cast<ParmVarDecl>(Pack)); break; } - + case Expr::MaterializeTemporaryExprClass: { mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr()); break; } - + + case Expr::CXXFoldExprClass: { + auto *FE = cast<CXXFoldExpr>(E); + if (FE->isLeftFold()) + Out << (FE->getInit() ? "fL" : "fl"); + else + Out << (FE->getInit() ? "fR" : "fr"); + + if (FE->getOperator() == BO_PtrMemD) + Out << "ds"; + else + mangleOperatorName( + BinaryOperator::getOverloadedOperator(FE->getOperator()), + /*Arity=*/2); + + if (FE->getLHS()) + mangleExpression(FE->getLHS()); + if (FE->getRHS()) + mangleExpression(FE->getRHS()); + break; + } + case Expr::CXXThisExprClass: Out << "fpT"; break; @@ -3251,8 +3315,8 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) { void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) { // <ctor-dtor-name> ::= C1 # complete object constructor // ::= C2 # base object constructor - // ::= C3 # complete object allocating constructor // + // In addition, C5 is a comdat name with C1 and C2 in it. switch (T) { case Ctor_Complete: Out << "C1"; @@ -3260,8 +3324,8 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) { case Ctor_Base: Out << "C2"; break; - case Ctor_CompleteAllocating: - Out << "C3"; + case Ctor_Comdat: + Out << "C5"; break; } } @@ -3271,6 +3335,7 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { // ::= D1 # complete object destructor // ::= D2 # base object destructor // + // In addition, D5 is a comdat name with D1, D2 and, if virtual, D0 in it. switch (T) { case Dtor_Deleting: Out << "D0"; @@ -3281,6 +3346,9 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { case Dtor_Base: Out << "D2"; break; + case Dtor_Comdat: + Out << "D5"; + break; } } @@ -3363,7 +3431,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) { // and pointer-to-function expressions are represented as a declaration not // an expression. We compensate for it here to produce the correct mangling. ValueDecl *D = A.getAsDecl(); - bool compensateMangling = !A.isDeclForReferenceParam(); + bool compensateMangling = !A.getParamTypeForDecl()->isReferenceType(); if (compensateMangling) { Out << 'X'; mangleOperatorName(OO_Amp, 1); @@ -3674,7 +3742,7 @@ void ItaniumMangleContextImpl::mangleCXXName(const NamedDecl *D, "Mangling declaration"); CXXNameMangler Mangler(*this, Out, D); - return Mangler.mangle(D); + Mangler.mangle(D); } void ItaniumMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D, @@ -3691,6 +3759,18 @@ void ItaniumMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D, Mangler.mangle(D); } +void ItaniumMangleContextImpl::mangleCXXCtorComdat(const CXXConstructorDecl *D, + raw_ostream &Out) { + CXXNameMangler Mangler(*this, Out, D, Ctor_Comdat); + Mangler.mangle(D); +} + +void ItaniumMangleContextImpl::mangleCXXDtorComdat(const CXXDestructorDecl *D, + raw_ostream &Out) { + CXXNameMangler Mangler(*this, Out, D, Dtor_Comdat); + Mangler.mangle(D); +} + void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &Out) { @@ -3851,3 +3931,4 @@ ItaniumMangleContext * ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { return new ItaniumMangleContextImpl(Context, Diags); } + diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp index fdc00e3..1a061c4 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -49,10 +49,11 @@ static void mangleFunctionBlock(MangleContext &Context, void MangleContext::anchor() { } -enum StdOrFastCC { - SOF_OTHER, - SOF_FAST, - SOF_STD +enum CCMangling { + CCM_Other, + CCM_Fast, + CCM_Vector, + CCM_Std }; static bool isExternC(const NamedDecl *ND) { @@ -61,20 +62,22 @@ static bool isExternC(const NamedDecl *ND) { return cast<VarDecl>(ND)->isExternC(); } -static StdOrFastCC getStdOrFastCallMangling(const ASTContext &Context, - const NamedDecl *ND) { +static CCMangling getCallingConvMangling(const ASTContext &Context, + const NamedDecl *ND) { const TargetInfo &TI = Context.getTargetInfo(); const llvm::Triple &Triple = TI.getTriple(); - if (!Triple.isOSWindows() || Triple.getArch() != llvm::Triple::x86) - return SOF_OTHER; + if (!Triple.isOSWindows() || + !(Triple.getArch() == llvm::Triple::x86 || + Triple.getArch() == llvm::Triple::x86_64)) + return CCM_Other; if (Context.getLangOpts().CPlusPlus && !isExternC(ND) && TI.getCXXABI() == TargetCXXABI::Microsoft) - return SOF_OTHER; + return CCM_Other; const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND); if (!FD) - return SOF_OTHER; + return CCM_Other; QualType T = FD->getType(); const FunctionType *FT = T->castAs<FunctionType>(); @@ -82,19 +85,21 @@ static StdOrFastCC getStdOrFastCallMangling(const ASTContext &Context, CallingConv CC = FT->getCallConv(); switch (CC) { default: - return SOF_OTHER; + return CCM_Other; case CC_X86FastCall: - return SOF_FAST; + return CCM_Fast; case CC_X86StdCall: - return SOF_STD; + return CCM_Std; + case CC_X86VectorCall: + return CCM_Vector; } } bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { const ASTContext &ASTContext = getASTContext(); - StdOrFastCC CC = getStdOrFastCallMangling(ASTContext, D); - if (CC != SOF_OTHER) + CCMangling CC = getCallingConvMangling(ASTContext, D); + if (CC != CCM_Other) return true; // In C, functions with no attributes never need to be mangled. Fastpath them. @@ -131,28 +136,35 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { } const ASTContext &ASTContext = getASTContext(); - StdOrFastCC CC = getStdOrFastCallMangling(ASTContext, D); + CCMangling CC = getCallingConvMangling(ASTContext, D); bool MCXX = shouldMangleCXXName(D); const TargetInfo &TI = Context.getTargetInfo(); - if (CC == SOF_OTHER || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) { - mangleCXXName(D, Out); + if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) { + if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) + mangleObjCMethodName(OMD, Out); + else + mangleCXXName(D, Out); return; } Out << '\01'; - if (CC == SOF_STD) + if (CC == CCM_Std) Out << '_'; - else + else if (CC == CCM_Fast) Out << '@'; if (!MCXX) Out << D->getIdentifier()->getName(); + else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) + mangleObjCMethodName(OMD, Out); else mangleCXXName(D, Out); const FunctionDecl *FD = cast<FunctionDecl>(D); const FunctionType *FT = FD->getType()->castAs<FunctionType>(); const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT); + if (CC == CCM_Vector) + Out << '@'; Out << '@'; if (!Proto) { Out << '0'; @@ -164,9 +176,11 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { if (!MD->isStatic()) ++ArgWords; for (const auto &AT : Proto->param_types()) - // Size should be aligned to DWORD boundary - ArgWords += llvm::RoundUpToAlignment(ASTContext.getTypeSize(AT), 32) / 32; - Out << 4 * ArgWords; + // Size should be aligned to pointer size. + ArgWords += llvm::RoundUpToAlignment(ASTContext.getTypeSize(AT), + TI.getPointerWidth(0)) / + TI.getPointerWidth(0); + Out << ((TI.getPointerWidth(0) / 8) * ArgWords); } void MangleContext::mangleGlobalBlock(const BlockDecl *BD, @@ -215,16 +229,28 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(Method, Stream); } else { - const NamedDecl *ND = cast<NamedDecl>(DC); - if (!shouldMangleDeclName(ND) && ND->getIdentifier()) - Stream << ND->getIdentifier()->getName(); - else { - // FIXME: We were doing a mangleUnqualifiedName() before, but that's - // a private member of a class that will soon itself be private to the - // Itanium C++ ABI object. What should we do now? Right now, I'm just - // calling the mangleName() method on the MangleContext; is there a - // better way? - mangleName(ND, Stream); + assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) && + "expected a NamedDecl or BlockDecl"); + if (isa<BlockDecl>(DC)) + for (; DC && isa<BlockDecl>(DC); DC = DC->getParent()) + (void) getBlockId(cast<BlockDecl>(DC), true); + assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) && + "expected a TranslationUnitDecl or a NamedDecl"); + if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) + mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); + else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) + mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); + else if (auto ND = dyn_cast<NamedDecl>(DC)) { + if (!shouldMangleDeclName(ND) && ND->getIdentifier()) + Stream << ND->getIdentifier()->getName(); + else { + // FIXME: We were doing a mangleUnqualifiedName() before, but that's + // a private member of a class that will soon itself be private to the + // Itanium C++ ABI object. What should we do now? Right now, I'm just + // calling the mangleName() method on the MangleContext; is there a + // better way? + mangleName(ND, Stream); + } } } Stream.flush(); diff --git a/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp b/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp deleted file mode 100644 index 5f40f03..0000000 --- a/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===--- MangleNumberingContext.cpp - Context for mangling numbers --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the LambdaMangleContext class, which keeps track of -// the Itanium C++ ABI mangling numbers for lambda expressions. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/MangleNumberingContext.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" - -using namespace clang; - -unsigned -MangleNumberingContext::getManglingNumber(const CXXMethodDecl *CallOperator) { - const FunctionProtoType *Proto - = CallOperator->getType()->getAs<FunctionProtoType>(); - ASTContext &Context = CallOperator->getASTContext(); - - QualType Key = Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), - FunctionProtoType::ExtProtoInfo()); - Key = Context.getCanonicalType(Key); - return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; -} - -unsigned -MangleNumberingContext::getManglingNumber(const BlockDecl *BD) { - // FIXME: Compute a BlockPointerType? Not obvious how. - const Type *Ty = nullptr; - return ++ManglingNumbers[Ty]; -} - -unsigned -MangleNumberingContext::getStaticLocalNumber(const VarDecl *VD) { - // FIXME: Compute a BlockPointerType? Not obvious how. - const Type *Ty = nullptr; - return ++ManglingNumbers[Ty]; -} diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp index 6870315..0603d3b 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp @@ -28,7 +28,28 @@ namespace { /// \brief Numbers things which need to correspond across multiple TUs. /// Typically these are things like static locals, lambdas, or blocks. class MicrosoftNumberingContext : public MangleNumberingContext { + llvm::DenseMap<const Type *, unsigned> ManglingNumbers; + unsigned LambdaManglingNumber; + unsigned StaticLocalNumber; + public: + MicrosoftNumberingContext() + : MangleNumberingContext(), LambdaManglingNumber(0), + StaticLocalNumber(0) {} + + unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { + return ++LambdaManglingNumber; + } + + unsigned getManglingNumber(const BlockDecl *BD) override { + const Type *Ty = nullptr; + return ++ManglingNumbers[Ty]; + } + + unsigned getStaticLocalNumber(const VarDecl *VD) override { + return ++StaticLocalNumber; + } + unsigned getManglingNumber(const VarDecl *VD, unsigned MSLocalManglingNumber) override { return MSLocalManglingNumber; diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index e6a6d09..72f90f6 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -27,7 +27,6 @@ #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" #include "llvm/Support/MathExtras.h" using namespace clang; @@ -161,7 +160,7 @@ public: unsigned &discriminator = Uniquifier[ND]; if (!discriminator) discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; - disc = discriminator; + disc = discriminator + 1; return true; } @@ -191,8 +190,8 @@ class MicrosoftCXXNameMangler { const NamedDecl *Structor; unsigned StructorType; - typedef llvm::StringMap<unsigned> BackRefMap; - BackRefMap NameBackReferences; + typedef llvm::SmallVector<std::string, 10> BackRefVec; + BackRefVec NameBackReferences; typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap; ArgBackRefMap TypeBackReferences; @@ -234,7 +233,7 @@ public: QualifierMangleMode QMM = QMM_Mangle); void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = nullptr, - bool ForceInstMethod = false); + bool ForceThisQuals = false); void mangleNestedName(const NamedDecl *ND); private: @@ -279,7 +278,8 @@ private: void mangleTemplateArgs(const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs); - void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA); + void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA, + const NamedDecl *Parm); }; } @@ -338,9 +338,7 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { bool MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) { - return SL->isAscii() || SL->isWide(); - // TODO: This needs to be updated when MSVC gains support for Unicode - // literals. + return true; } void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { @@ -441,7 +439,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { mangleQualifiers(Ty.getQualifiers(), false); } else { mangleType(Ty, SR, QMM_Drop); - mangleQualifiers(Ty.getLocalQualifiers(), false); + mangleQualifiers(Ty.getQualifiers(), false); } } @@ -801,10 +799,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { // <postfix> ::= <unqualified-name> [<postfix>] // ::= <substitution> [<postfix>] - if (isLambda(ND)) - return; - - const DeclContext *DC = ND->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(ND); while (!DC->isTranslationUnit()) { if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) { @@ -856,6 +851,8 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) { // <operator-name> ::= ?_E # vector deleting destructor // FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need // it. + case Dtor_Comdat: + llvm_unreachable("not expecting a COMDAT"); } llvm_unreachable("Unsupported dtor type?"); } @@ -994,22 +991,14 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) { // <source name> ::= <identifier> @ - BackRefMap::iterator Found; - if (NameBackReferences.size() < 10) { - size_t Size = NameBackReferences.size(); - bool Inserted; - std::tie(Found, Inserted) = - NameBackReferences.insert(std::make_pair(Name, Size)); - if (Inserted) - Found = NameBackReferences.end(); - } else { - Found = NameBackReferences.find(Name); - } - + BackRefVec::iterator Found = + std::find(NameBackReferences.begin(), NameBackReferences.end(), Name); if (Found == NameBackReferences.end()) { + if (NameBackReferences.size() < 10) + NameBackReferences.push_back(Name); Out << Name << '@'; } else { - Out << Found->second; + Out << (Found - NameBackReferences.begin()); } } @@ -1025,7 +1014,7 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( // Templates have their own context for back references. ArgBackRefMap OuterArgsContext; - BackRefMap OuterTemplateContext; + BackRefVec OuterTemplateContext; NameBackReferences.swap(OuterTemplateContext); TypeBackReferences.swap(OuterArgsContext); @@ -1051,8 +1040,10 @@ void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, // Make sure booleans are encoded as 0/1. if (IsBoolean && Value.getBoolValue()) mangleNumber(1); - else + else if (Value.isSigned()) mangleNumber(Value.getSExtValue()); + else + mangleNumber(Value.getZExtValue()); } void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { @@ -1104,12 +1095,18 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { void MicrosoftCXXNameMangler::mangleTemplateArgs( const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) { // <template-args> ::= <template-arg>+ + const TemplateParameterList *TPL = TD->getTemplateParameters(); + assert(TPL->size() == TemplateArgs.size() && + "size mismatch between args and parms!"); + + unsigned Idx = 0; for (const TemplateArgument &TA : TemplateArgs.asArray()) - mangleTemplateArg(TD, TA); + mangleTemplateArg(TD, TA, TPL->getParam(Idx++)); } void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, - const TemplateArgument &TA) { + const TemplateArgument &TA, + const NamedDecl *Parm) { // <template-arg> ::= <type> // ::= <integer-literal> // ::= <member-data-pointer> @@ -1142,7 +1139,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, else mangle(FD, "$1?"); } else { - mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?"); + mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?"); } break; } @@ -1172,18 +1169,33 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, case TemplateArgument::Pack: { ArrayRef<TemplateArgument> TemplateArgs = TA.getPackAsArray(); if (TemplateArgs.empty()) { - Out << "$S"; + if (isa<TemplateTypeParmDecl>(Parm) || + isa<TemplateTemplateParmDecl>(Parm)) + Out << "$$V"; + else if (isa<NonTypeTemplateParmDecl>(Parm)) + Out << "$S"; + else + llvm_unreachable("unexpected template parameter decl!"); } else { for (const TemplateArgument &PA : TemplateArgs) - mangleTemplateArg(TD, PA); + mangleTemplateArg(TD, PA, Parm); } break; } - case TemplateArgument::Template: - mangleType(cast<TagDecl>( - TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl())); + case TemplateArgument::Template: { + const NamedDecl *ND = + TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl(); + if (const auto *TD = dyn_cast<TagDecl>(ND)) { + mangleType(TD); + } else if (isa<TypeAliasDecl>(ND)) { + Out << "$$Y"; + mangleName(ND); + } else { + llvm_unreachable("unexpected template template NamedDecl!"); + } break; } + } } void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, @@ -1473,6 +1485,8 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, case BuiltinType::Int128: Out << "_L"; break; case BuiltinType::UInt128: Out << "_M"; break; case BuiltinType::Bool: Out << "_N"; break; + case BuiltinType::Char16: Out << "_S"; break; + case BuiltinType::Char32: Out << "_U"; break; case BuiltinType::WChar_S: case BuiltinType::WChar_U: Out << "_W"; break; @@ -1498,8 +1512,6 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, case BuiltinType::NullPtr: Out << "$$T"; break; - case BuiltinType::Char16: - case BuiltinType::Char32: case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -1518,8 +1530,13 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, // Structors only appear in decls, so at this point we know it's not a // structor type. // FIXME: This may not be lambda-friendly. - Out << "$$A6"; - mangleFunctionType(T); + if (T->getTypeQuals() || T->getRefQualifier() != RQ_None) { + Out << "$$A8@@"; + mangleFunctionType(T, /*D=*/nullptr, /*ForceThisQuals=*/true); + } else { + Out << "$$A6"; + mangleFunctionType(T); + } } void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, SourceRange) { @@ -1528,7 +1545,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, const FunctionDecl *D, - bool ForceInstMethod) { + bool ForceThisQuals) { // <function-type> ::= <this-cvr-qualifiers> <calling-convention> // <return-type> <argument-list> <throw-spec> const FunctionProtoType *Proto = cast<FunctionProtoType>(T); @@ -1536,21 +1553,21 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, SourceRange Range; if (D) Range = D->getSourceRange(); - bool IsStructor = false, IsInstMethod = ForceInstMethod; + bool IsStructor = false, HasThisQuals = ForceThisQuals; if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) { if (MD->isInstance()) - IsInstMethod = true; + HasThisQuals = true; if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) IsStructor = true; } // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. - if (IsInstMethod) { + if (HasThisQuals) { Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals()); - manglePointerExtQualifiers(Quals, nullptr); + manglePointerExtQualifiers(Quals, /*PointeeType=*/nullptr); mangleRefQualifier(Proto->getRefQualifier()); - mangleQualifiers(Quals, false); + mangleQualifiers(Quals, /*IsMember=*/false); } mangleCallingConvention(T); @@ -1670,6 +1687,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { // ::= H # __export __stdcall // ::= I # __fastcall // ::= J # __export __fastcall + // ::= Q # __vectorcall // The 'export' calling conventions are from a bygone era // (*cough*Win16*cough*) when functions were declared for export with // that keyword. (It didn't actually export them, it just made them so @@ -1686,6 +1704,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { case CC_X86ThisCall: Out << 'E'; break; case CC_X86StdCall: Out << 'G'; break; case CC_X86FastCall: Out << 'I'; break; + case CC_X86VectorCall: Out << 'Q'; break; } } void MicrosoftCXXNameMangler::mangleThrowSpecification( @@ -2331,7 +2350,7 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD, void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, raw_ostream &Out) { - // TODO: This is not correct, especially with respect to MSVC2013. MSVC2013 + // TODO: This is not correct, especially with respect to VS "14". VS "14" // utilizes thread local variables to implement thread safe, re-entrant // initialization for statics. They no longer differentiate between an // externally visible and non-externally visible static with respect to @@ -2420,14 +2439,10 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, Mangler.getStream() << "\01??_C@_"; // <char-type>: The "kind" of string literal is encoded into the mangled name. - // TODO: This needs to be updated when MSVC gains support for unicode - // literals. - if (SL->isAscii()) - Mangler.getStream() << '0'; - else if (SL->isWide()) + if (SL->isWide()) Mangler.getStream() << '1'; else - llvm_unreachable("unexpected string literal kind!"); + Mangler.getStream() << '0'; // <literal-length>: The next part of the mangled name consists of the length // of the string. @@ -2506,42 +2521,16 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, } else if (isLetter(Byte & 0x7f)) { Mangler.getStream() << '?' << static_cast<char>(Byte & 0x7f); } else { - switch (Byte) { - case ',': - Mangler.getStream() << "?0"; - break; - case '/': - Mangler.getStream() << "?1"; - break; - case '\\': - Mangler.getStream() << "?2"; - break; - case ':': - Mangler.getStream() << "?3"; - break; - case '.': - Mangler.getStream() << "?4"; - break; - case ' ': - Mangler.getStream() << "?5"; - break; - case '\n': - Mangler.getStream() << "?6"; - break; - case '\t': - Mangler.getStream() << "?7"; - break; - case '\'': - Mangler.getStream() << "?8"; - break; - case '-': - Mangler.getStream() << "?9"; - break; - default: - Mangler.getStream() << "?$"; - Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf)); - Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf)); - break; + const char SpecialChars[] = {',', '/', '\\', ':', '.', + ' ', '\n', '\t', '\'', '-'}; + const char *Pos = + std::find(std::begin(SpecialChars), std::end(SpecialChars), Byte); + if (Pos != std::end(SpecialChars)) { + Mangler.getStream() << '?' << (Pos - std::begin(SpecialChars)); + } else { + Mangler.getStream() << "?$"; + Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf)); + Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf)); } } }; @@ -2550,7 +2539,10 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, unsigned NumCharsToMangle = std::min(32U, SL->getLength()); for (unsigned I = 0, E = NumCharsToMangle * SL->getCharByteWidth(); I != E; ++I) - MangleByte(GetBigEndianByte(I)); + if (SL->isWide()) + MangleByte(GetBigEndianByte(I)); + else + MangleByte(GetLittleEndianByte(I)); // Encode the NUL terminator if there is room. if (NumCharsToMangle < 32) diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp index 986b3b5..3dc750a 100644 --- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp @@ -10,6 +10,7 @@ #include "clang/AST/NSAPI.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -46,6 +47,10 @@ Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const { Sel = Ctx.Selectors.getUnarySelector( &Ctx.Idents.get("stringWithUTF8String")); break; + case NSStr_initWithUTF8String: + Sel = Ctx.Selectors.getUnarySelector( + &Ctx.Idents.get("initWithUTF8String")); + break; case NSStr_stringWithCStringEncoding: { IdentifierInfo *KeyIdents[] = { &Ctx.Idents.get("stringWithCString"), @@ -379,6 +384,32 @@ bool NSAPI::isObjCNSUIntegerType(QualType T) const { return isObjCTypedef(T, "NSUInteger", NSUIntegerId); } +StringRef NSAPI::GetNSIntegralKind(QualType T) const { + if (!Ctx.getLangOpts().ObjC1 || T.isNull()) + return StringRef(); + + while (const TypedefType *TDT = T->getAs<TypedefType>()) { + StringRef NSIntegralResust = + llvm::StringSwitch<StringRef>( + TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName()) + .Case("int8_t", "int8_t") + .Case("int16_t", "int16_t") + .Case("int32_t", "int32_t") + .Case("NSInteger", "NSInteger") + .Case("int64_t", "int64_t") + .Case("uint8_t", "uint8_t") + .Case("uint16_t", "uint16_t") + .Case("uint32_t", "uint32_t") + .Case("NSUInteger", "NSUInteger") + .Case("uint64_t", "uint64_t") + .Default(StringRef()); + if (!NSIntegralResust.empty()) + return NSIntegralResust; + T = TDT->desugar(); + } + return StringRef(); +} + bool NSAPI::isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const { if (!Ctx.getLangOpts().ObjC1) diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 1f041aa..50a0050 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -66,7 +66,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, "Broken nested name specifier"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(StoredNamespaceOrAlias); + Mockup.Prefix.setInt(StoredDecl); Mockup.Specifier = const_cast<NamespaceDecl *>(NS); return FindOrInsert(Context, Mockup); } @@ -82,7 +82,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, "Broken nested name specifier"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(StoredNamespaceOrAlias); + Mockup.Prefix.setInt(StoredDecl); Mockup.Specifier = Alias; return FindOrInsert(Context, Mockup); } @@ -118,6 +118,16 @@ NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { return Context.GlobalNestedNameSpecifier; } +NestedNameSpecifier * +NestedNameSpecifier::SuperSpecifier(const ASTContext &Context, + CXXRecordDecl *RD) { + NestedNameSpecifier Mockup; + Mockup.Prefix.setPointer(nullptr); + Mockup.Prefix.setInt(StoredDecl); + Mockup.Specifier = RD; + return FindOrInsert(Context, Mockup); +} + NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { if (!Specifier) return Global; @@ -126,9 +136,12 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { case StoredIdentifier: return Identifier; - case StoredNamespaceOrAlias: - return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace - : NamespaceAlias; + case StoredDecl: { + NamedDecl *ND = static_cast<NamedDecl *>(Specifier); + if (isa<CXXRecordDecl>(ND)) + return Super; + return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias; + } case StoredTypeSpec: return TypeSpec; @@ -140,24 +153,29 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { llvm_unreachable("Invalid NNS Kind!"); } -/// \brief Retrieve the namespace stored in this nested name -/// specifier. +/// \brief Retrieve the namespace stored in this nested name specifier. NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { - if (Prefix.getInt() == StoredNamespaceOrAlias) + if (Prefix.getInt() == StoredDecl) return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); return nullptr; } -/// \brief Retrieve the namespace alias stored in this nested name -/// specifier. +/// \brief Retrieve the namespace alias stored in this nested name specifier. NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { - if (Prefix.getInt() == StoredNamespaceOrAlias) + if (Prefix.getInt() == StoredDecl) return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); return nullptr; } +/// \brief Retrieve the record declaration stored in this nested name specifier. +CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { + if (Prefix.getInt() == StoredDecl) + return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier)); + + return nullptr; +} /// \brief Whether this nested name specifier refers to a dependent /// type or not. @@ -172,6 +190,15 @@ bool NestedNameSpecifier::isDependent() const { case Global: return false; + case Super: { + CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier); + for (const auto &Base : RD->bases()) + if (Base.getType()->isDependentType()) + return true; + + return false; + } + case TypeSpec: case TypeSpecWithTemplate: return getAsType()->isDependentType(); @@ -191,8 +218,9 @@ bool NestedNameSpecifier::isInstantiationDependent() const { case Namespace: case NamespaceAlias: case Global: + case Super: return false; - + case TypeSpec: case TypeSpecWithTemplate: return getAsType()->isInstantiationDependentType(); @@ -209,6 +237,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const { case Namespace: case NamespaceAlias: case Global: + case Super: return false; case TypeSpec: @@ -246,6 +275,10 @@ NestedNameSpecifier::print(raw_ostream &OS, case Global: break; + case Super: + OS << "__super"; + break; + case TypeSpecWithTemplate: OS << "template "; // Fall through to print the type. @@ -304,6 +337,7 @@ NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Super: // The location of the identifier or namespace name. Length += sizeof(unsigned); break; @@ -369,6 +403,7 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Super: return SourceRange(LoadSourceLocation(Data, Offset), LoadSourceLocation(Data, Offset + sizeof(unsigned))); @@ -552,6 +587,17 @@ void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); } +void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, + CXXRecordDecl *RD, + SourceLocation SuperLoc, + SourceLocation ColonColonLoc) { + Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); + + // Push source-location info into the buffer. + SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); +} + void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R) { @@ -583,6 +629,7 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, } case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: break; } diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index b3deeba..0d070a4 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -636,23 +636,12 @@ protected: HasOwnVFPtr(false), FirstNearlyEmptyVBase(nullptr) {} - /// Reset this RecordLayoutBuilder to a fresh state, using the given - /// alignment as the initial alignment. This is used for the - /// correct layout of vb-table pointers in MSVC. - void resetWithTargetAlignment(CharUnits TargetAlignment) { - const ASTContext &Context = this->Context; - EmptySubobjectMap *EmptySubobjects = this->EmptySubobjects; - this->~RecordLayoutBuilder(); - new (this) RecordLayoutBuilder(Context, EmptySubobjects); - Alignment = UnpackedAlignment = TargetAlignment; - } - void Layout(const RecordDecl *D); void Layout(const CXXRecordDecl *D); void Layout(const ObjCInterfaceDecl *D); void LayoutFields(const RecordDecl *D); - void LayoutField(const FieldDecl *D); + void LayoutField(const FieldDecl *D, bool InsertExtraPadding); void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize, bool FieldPacked, const FieldDecl *D); void LayoutBitField(const FieldDecl *D); @@ -1104,7 +1093,7 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, // Only lay out the virtual base if it's not an indirect primary base. if (!IndirectPrimaryBase) { // Only visit virtual bases once. - if (!VisitedVirtualBases.insert(BaseDecl)) + if (!VisitedVirtualBases.insert(BaseDecl).second) continue; const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl); @@ -1331,7 +1320,7 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { // Layout each ivar sequentially. for (const ObjCIvarDecl *IVD = D->all_declared_ivar_begin(); IVD; IVD = IVD->getNextIvar()) - LayoutField(IVD); + LayoutField(IVD, false); // Finally, round the size of the total struct up to the alignment of the // struct itself. @@ -1341,8 +1330,22 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. - for (const auto *Field : D->fields()) - LayoutField(Field); + bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true); + bool HasFlexibleArrayMember = D->hasFlexibleArrayMember(); + for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) { + auto Next(I); + ++Next; + LayoutField(*I, + InsertExtraPadding && (Next != End || !HasFlexibleArrayMember)); + } +} + +// Rounds the specified size to have it a multiple of the char size. +static uint64_t +roundUpSizeToCharAlignment(uint64_t Size, + const ASTContext &Context) { + uint64_t CharAlignment = Context.getTargetInfo().getCharAlign(); + return llvm::RoundUpToAlignment(Size, CharAlignment); } void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, @@ -1382,7 +1385,9 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit; if (IsUnion) { - setDataSize(std::max(getDataSizeInBits(), FieldSize)); + uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, + Context); + setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize)); FieldOffset = 0; } else { // The bitfield is allocated starting at the next offset aligned @@ -1413,9 +1418,9 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); uint64_t FieldSize = D->getBitWidthValue(Context); - std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType()); - uint64_t TypeSize = FieldInfo.first; - unsigned FieldAlign = FieldInfo.second; + TypeInfo FieldInfo = Context.getTypeInfo(D->getType()); + uint64_t TypeSize = FieldInfo.Width; + unsigned FieldAlign = FieldInfo.Align; // UnfilledBitsInLastUnit is the difference between the end of the // last allocated bitfield (i.e. the first bit offset available for @@ -1607,9 +1612,9 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // For unions, this is just a max operation, as usual. if (IsUnion) { - // FIXME: I think FieldSize should be TypeSize here. - setDataSize(std::max(getDataSizeInBits(), FieldSize)); - + uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, + Context); + setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize)); // For non-zero-width bitfields in ms_struct structs, allocate a new // storage unit if necessary. } else if (IsMsStruct && FieldSize) { @@ -1645,7 +1650,8 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { Context.toCharUnitsFromBits(UnpackedFieldAlign)); } -void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { +void RecordLayoutBuilder::LayoutField(const FieldDecl *D, + bool InsertExtraPadding) { if (D->isBitField()) { LayoutBitField(D); return; @@ -1749,6 +1755,15 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { Context.toBits(UnpackedFieldOffset), Context.toBits(UnpackedFieldAlign), FieldPacked, D); + if (InsertExtraPadding) { + CharUnits ASanAlignment = CharUnits::fromQuantity(8); + CharUnits ExtraSizeForAsan = ASanAlignment; + if (FieldSize % ASanAlignment) + ExtraSizeForAsan += + ASanAlignment - CharUnits::fromQuantity(FieldSize % ASanAlignment); + FieldSize += ExtraSizeForAsan; + } + // Reserve space for this field. uint64_t FieldSizeInBits = Context.toBits(FieldSize); if (IsUnion) @@ -2097,7 +2112,7 @@ static bool isMsLayout(const RecordDecl* D) { // * There is a distinction between alignment and required alignment. // __declspec(align) changes the required alignment of a struct. This // alignment is _always_ obeyed, even in the presence of #pragma pack. A -// record inherites required alignment from all of its fields an bases. +// record inherits required alignment from all of its fields and bases. // * __declspec(align) on bitfields has the effect of changing the bitfield's // alignment instead of its required alignment. This is the only known way // to make the alignment of a struct bigger than 8. Interestingly enough @@ -2181,8 +2196,9 @@ public: FieldOffsets.push_back(FieldOffset); } /// \brief Compute the set of virtual bases for which vtordisps are required. - llvm::SmallPtrSet<const CXXRecordDecl *, 2> - computeVtorDispSet(const CXXRecordDecl *RD); + void computeVtorDispSet( + llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet, + const CXXRecordDecl *RD) const; const ASTContext &Context; /// \brief The size of the record being laid out. CharUnits Size; @@ -2203,6 +2219,8 @@ public: CharUnits CurrentBitfieldSize; /// \brief Offset to the virtual base table pointer (if one exists). CharUnits VBPtrOffset; + /// \brief Minimum record size possible. + CharUnits MinEmptyStructSize; /// \brief The size and alignment info of a pointer. ElementInfo PointerInfo; /// \brief The primary base class (if one exists). @@ -2260,12 +2278,18 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( MicrosoftRecordLayoutBuilder::ElementInfo MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( const FieldDecl *FD) { + // Get the alignment of the field type's natural alignment, ignore any + // alignment attributes. ElementInfo Info; std::tie(Info.Size, Info.Alignment) = - Context.getTypeInfoInChars(FD->getType()); - // Respect align attributes. - CharUnits FieldRequiredAlignment = + Context.getTypeInfoInChars(FD->getType()->getUnqualifiedDesugaredType()); + // Respect align attributes on the field. + CharUnits FieldRequiredAlignment = Context.toCharUnitsFromBits(FD->getMaxAlignment()); + // Respect align attributes on the type. + if (Context.isAlignmentRequired(FD->getType())) + FieldRequiredAlignment = std::max( + Context.getTypeAlignInChars(FD->getType()), FieldRequiredAlignment); // Respect attributes applied to subobjects of the field. if (FD->isBitField()) // For some reason __declspec align impacts alignment rather than required @@ -2292,6 +2316,8 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( } void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) { + // For C record layout, zero-sized records always have size 4. + MinEmptyStructSize = CharUnits::fromQuantity(4); initializeLayout(RD); layoutFields(RD); DataSize = Size = Size.RoundUpToAlignment(Alignment); @@ -2301,6 +2327,8 @@ void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) { } void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) { + // The C++ standard says that empty structs have size 1. + MinEmptyStructSize = CharUnits::One(); initializeLayout(RD); initializeCXXLayout(RD); layoutNonVirtualBases(RD); @@ -2599,14 +2627,14 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { } VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment); // Compute the vtordisp set. - llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet = - computeVtorDispSet(RD); + llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet; + computeVtorDispSet(HasVtorDispSet, RD); // Iterate through the virtual bases and lay them out. const ASTRecordLayout *PreviousBaseLayout = nullptr; for (const CXXBaseSpecifier &VBase : RD->vbases()) { const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl(); const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl); - bool HasVtordisp = HasVtordispSet.count(BaseDecl); + bool HasVtordisp = HasVtorDispSet.count(BaseDecl) > 0; // Insert padding between two bases if the left first one is zero sized or // contains a zero sized subobject and the right is zero sized or one leads // with a zero sized base. The padding between virtual bases is 4 @@ -2629,7 +2657,7 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) { // Respect required alignment. Note that in 32-bit mode Required alignment - // may be 0 nad cause size not to be updated. + // may be 0 and cause size not to be updated. DataSize = Size; if (!RequiredAlignment.isZero()) { Alignment = std::max(Alignment, RequiredAlignment); @@ -2639,11 +2667,15 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) { RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment); Size = Size.RoundUpToAlignment(RoundingAlignment); } - // Zero-sized structures have size equal to their alignment. if (Size.isZero()) { EndsWithZeroSizedObject = true; LeadsWithZeroSizedBase = true; - Size = Alignment; + // Zero-sized structures have size equal to their alignment if a + // __declspec(align) came into play. + if (RequiredAlignment >= MinEmptyStructSize) + Size = Alignment; + else + Size = MinEmptyStructSize; } } @@ -2665,10 +2697,9 @@ RequiresVtordisp(const llvm::SmallPtrSetImpl<const CXXRecordDecl *> & return false; } -llvm::SmallPtrSet<const CXXRecordDecl *, 2> -MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) { - llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet; - +void MicrosoftRecordLayoutBuilder::computeVtorDispSet( + llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet, + const CXXRecordDecl *RD) const { // /vd2 or #pragma vtordisp(2): Always use vtordisps for virtual bases with // vftables. if (RD->getMSVtorDispMode() == MSVtorDispAttr::ForVFTable) { @@ -2678,7 +2709,7 @@ MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) { if (Layout.hasExtendableVFPtr()) HasVtordispSet.insert(BaseDecl); } - return HasVtordispSet; + return; } // If any of our bases need a vtordisp for this type, so do we. Check our @@ -2695,7 +2726,7 @@ MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) { // * #pragma vtordisp(0) or the /vd0 flag are in use. if ((!RD->hasUserDeclaredConstructor() && !RD->hasUserDeclaredDestructor()) || RD->getMSVtorDispMode() == MSVtorDispAttr::Never) - return HasVtordispSet; + return; // /vd1 or #pragma vtordisp(1): Try to guess based on whether we think it's // possible for a partially constructed object with virtual base overrides to // escape a non-trivial constructor. @@ -2706,9 +2737,9 @@ MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) { // vtordisp. llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work; llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods; - // Seed the working set with our non-destructor virtual methods. + // Seed the working set with our non-destructor, non-pure virtual methods. for (const CXXMethodDecl *MD : RD->methods()) - if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) + if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure()) Work.insert(MD); while (!Work.empty()) { const CXXMethodDecl *MD = *Work.begin(); @@ -2730,7 +2761,6 @@ MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) { RequiresVtordisp(BasesWithOverriddenMethods, BaseDecl)) HasVtordispSet.insert(BaseDecl); } - return HasVtordispSet; } /// \brief Get or compute information about the layout of the specified record diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index a8483dc..68c7e72 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -104,6 +104,26 @@ Stmt *Stmt::IgnoreImplicit() { return s; } +/// \brief Skip no-op (attributed, compound) container stmts and skip captured +/// stmt at the top, if \a IgnoreCaptured is true. +Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) { + Stmt *S = this; + if (IgnoreCaptured) + if (auto CapS = dyn_cast_or_null<CapturedStmt>(S)) + S = CapS->getCapturedStmt(); + while (true) { + if (auto AS = dyn_cast_or_null<AttributedStmt>(S)) + S = AS->getSubStmt(); + else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) { + if (CS->size() != 1) + break; + S = CS->body_back(); + } else + break; + } + return S; +} + /// \brief Strip off all label-like statements. /// /// This will strip off label statements, case statements, attributed @@ -254,7 +274,7 @@ SourceLocation Stmt::getLocEnd() const { CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts, SourceLocation LB, SourceLocation RB) - : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) { + : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) { CompoundStmtBits.NumStmts = Stmts.size(); assert(CompoundStmtBits.NumStmts == Stmts.size() && "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); @@ -357,6 +377,11 @@ unsigned AsmStmt::getNumPlusOperands() const { return Res; } +char GCCAsmStmt::AsmStringPiece::getModifier() const { + assert(isOperand() && "Only Operands can have modifiers."); + return isLetter(Str[0]) ? Str[0] : '\0'; +} + StringRef GCCAsmStmt::getClobber(unsigned i) const { return getClobberStringLiteral(i)->getString(); } @@ -517,17 +542,25 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, CurStringPiece.clear(); } - // Handle %x4 and %x[foo] by capturing x as the modifier character. - char Modifier = '\0'; + // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that + // don't (e.g., %x4). 'x' following the '%' is the constraint modifier. + + const char *Begin = CurPtr - 1; // Points to the character following '%'. + const char *Percent = Begin - 1; // Points to '%'. + if (isLetter(EscapedChar)) { if (CurPtr == StrEnd) { // Premature end. DiagOffs = CurPtr-StrStart-1; return diag::err_asm_invalid_escape; } - Modifier = EscapedChar; EscapedChar = *CurPtr++; } + const TargetInfo &TI = C.getTargetInfo(); + const SourceManager &SM = C.getSourceManager(); + const LangOptions &LO = C.getLangOpts(); + + // Handle operands that don't have asmSymbolicName (e.g., %x4). if (isDigit(EscapedChar)) { // %n - Assembler operand n unsigned N = 0; @@ -543,11 +576,21 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, return diag::err_asm_invalid_operand_number; } - Pieces.push_back(AsmStringPiece(N, Modifier)); + // Str contains "x4" (Operand without the leading %). + std::string Str(Begin, CurPtr - Begin); + + // (BeginLoc, EndLoc) represents the range of the operand we are currently + // processing. Unlike Str, the range includes the leading '%'. + SourceLocation BeginLoc = + getAsmString()->getLocationOfByte(Percent - StrStart, SM, LO, TI); + SourceLocation EndLoc = + getAsmString()->getLocationOfByte(CurPtr - StrStart, SM, LO, TI); + + Pieces.push_back(AsmStringPiece(N, Str, BeginLoc, EndLoc)); continue; } - // Handle %[foo], a symbolic operand reference. + // Handle operands that have asmSymbolicName (e.g., %x[foo]). if (EscapedChar == '[') { DiagOffs = CurPtr-StrStart-1; @@ -566,7 +609,18 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, DiagOffs = CurPtr-StrStart; return diag::err_asm_unknown_symbolic_operand_name; } - Pieces.push_back(AsmStringPiece(N, Modifier)); + + // Str contains "x[foo]" (Operand without the leading %). + std::string Str(Begin, NameEnd + 1 - Begin); + + // (BeginLoc, EndLoc) represents the range of the operand we are currently + // processing. Unlike Str, the range includes the leading '%'. + SourceLocation BeginLoc = + getAsmString()->getLocationOfByte(Percent - StrStart, SM, LO, TI); + SourceLocation EndLoc = + getAsmString()->getLocationOfByte(NameEnd + 1 - StrStart, SM, LO, TI); + + Pieces.push_back(AsmStringPiece(N, Str, BeginLoc, EndLoc)); CurPtr = NameEnd+1; continue; @@ -956,20 +1010,22 @@ Expr* ReturnStmt::getRetValue() { return cast_or_null<Expr>(RetExpr); } -SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler, int HandlerIndex, int HandlerParentIndex) - : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc), - HandlerIndex(HandlerIndex), HandlerParentIndex(HandlerParentIndex) { - Children[TRY] = TryBlock; +SEHTryStmt::SEHTryStmt(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) + : Stmt(SEHTryStmtClass), + IsCXXTry(IsCXXTry), + TryLoc(TryLoc) +{ + Children[TRY] = TryBlock; Children[HANDLER] = Handler; } -SEHTryStmt *SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry, +SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler, int HandlerIndex, - int HandlerParentIndex) { - return new (C) SEHTryStmt(IsCXXTry, TryLoc, TryBlock, Handler, HandlerIndex, - HandlerParentIndex); + Stmt *Handler) { + return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); } SEHExceptStmt* SEHTryStmt::getExceptHandler() const { @@ -1120,17 +1176,24 @@ StmtRange OMPClause::children() { llvm_unreachable("unknown OMPClause"); } -OMPPrivateClause *OMPPrivateClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { +void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), varlist_end()); +} + +OMPPrivateClause * +OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL) { + // Allocate space for private variables and initializer expressions. void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); - OMPPrivateClause *Clause = new (Mem) OMPPrivateClause(StartLoc, LParenLoc, - EndLoc, VL.size()); + 2 * sizeof(Expr *) * VL.size()); + OMPPrivateClause *Clause = + new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setPrivateCopies(PrivateVL); return Clause; } @@ -1138,23 +1201,35 @@ OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); + 2 * sizeof(Expr *) * N); return new (Mem) OMPPrivateClause(N); } -OMPFirstprivateClause *OMPFirstprivateClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { +void OMPFirstprivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), varlist_end()); +} + +void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of inits is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), getPrivateCopies().end()); +} + +OMPFirstprivateClause * +OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, + ArrayRef<Expr *> InitVL) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); - OMPFirstprivateClause *Clause = new (Mem) OMPFirstprivateClause(StartLoc, - LParenLoc, - EndLoc, - VL.size()); + 3 * sizeof(Expr *) * VL.size()); + OMPFirstprivateClause *Clause = + new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setPrivateCopies(PrivateVL); + Clause->setInits(InitVL); return Clause; } @@ -1162,7 +1237,7 @@ OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); + 3 * sizeof(Expr *) * N); return new (Mem) OMPFirstprivateClause(N); } @@ -1306,6 +1381,24 @@ void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) { std::copy(Clauses.begin(), Clauses.end(), getClauses().begin()); } +void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) { + assert(A.size() == getCollapsedNumber() && + "Number of loop counters is not the same as the collapsed number"); + std::copy(A.begin(), A.end(), getCounters().begin()); +} + +void OMPLoopDirective::setUpdates(ArrayRef<Expr *> A) { + assert(A.size() == getCollapsedNumber() && + "Number of counter updates is not the same as the collapsed number"); + std::copy(A.begin(), A.end(), getUpdates().begin()); +} + +void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) { + assert(A.size() == getCollapsedNumber() && + "Number of counter finals is not the same as the collapsed number"); + std::copy(A.begin(), A.end(), getFinals().begin()); +} + OMPReductionClause *OMPReductionClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, @@ -1348,6 +1441,21 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) { return new (Mem) OMPFlushClause(N); } +const OMPClause * +OMPExecutableDirective::getSingleClause(OpenMPClauseKind K) const { + auto ClauseFilter = + [=](const OMPClause *C) -> bool { return C->getClauseKind() == K; }; + OMPExecutableDirective::filtered_clause_iterator<decltype(ClauseFilter)> I( + clauses(), ClauseFilter); + + if (I) { + auto *Clause = *I; + assert(!++I && "There are at least 2 clauses of the specified kind"); + return Clause; + } + return nullptr; +} + OMPParallelDirective *OMPParallelDirective::Create( const ASTContext &C, SourceLocation StartLoc, @@ -1378,15 +1486,27 @@ OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C, OMPSimdDirective * OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>()); void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); OMPSimdDirective *Dir = new (Mem) OMPSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); Dir->setClauses(Clauses); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond, Exprs.SeparatedCond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setCounters(Exprs.Counters); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); return Dir; } @@ -1397,22 +1517,42 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C, unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>()); void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses); } OMPForDirective * OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); OMPForDirective *Dir = new (Mem) OMPForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); Dir->setClauses(Clauses); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond, Exprs.SeparatedCond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); return Dir; } @@ -1423,10 +1563,57 @@ OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C, unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); return new (Mem) OMPForDirective(CollapsedNum, NumClauses); } +OMPForSimdDirective * +OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); + OMPForSimdDirective *Dir = new (Mem) + OMPForSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond, Exprs.SeparatedCond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + return Dir; +} + +OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); + return new (Mem) OMPForSimdDirective(CollapsedNum, NumClauses); +} + OMPSectionsDirective *OMPSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { @@ -1537,19 +1724,36 @@ OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPCriticalDirective(); } -OMPParallelForDirective * -OMPParallelForDirective::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt) { +OMPParallelForDirective *OMPParallelForDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_parallel_for)); OMPParallelForDirective *Dir = new (Mem) OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); Dir->setClauses(Clauses); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond, Exprs.SeparatedCond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); return Dir; } @@ -1558,11 +1762,57 @@ OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_parallel_for)); return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses); } +OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); + OMPParallelForSimdDirective *Dir = new (Mem) OMPParallelForSimdDirective( + StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond, Exprs.SeparatedCond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + return Dir; +} + +OMPParallelForSimdDirective * +OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); + return new (Mem) OMPParallelForSimdDirective(CollapsedNum, NumClauses); +} + OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { @@ -1678,3 +1928,103 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPFlushDirective(NumClauses); } +OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPOrderedDirective *Dir = new (Mem) OMPOrderedDirective(StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPOrderedDirective(); +} + +OMPAtomicDirective * +OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + 4 * sizeof(Stmt *)); + OMPAtomicDirective *Dir = + new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setX(X); + Dir->setV(V); + Dir->setExpr(E); + return Dir; +} + +OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 4 * sizeof(Stmt *)); + return new (Mem) OMPAtomicDirective(NumClauses); +} + +OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTargetDirective *Dir = + new (Mem) OMPTargetDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTargetDirective(NumClauses); +} + +OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTeamsDirective *Dir = + new (Mem) OMPTeamsDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTeamsDirective(NumClauses); +} + diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 1fdad9f..927a679 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -665,6 +665,22 @@ void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) { OS << "mergeable"; } +void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; } + +void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; } + +void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) { + OS << "update"; +} + +void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) { + OS << "capture"; +} + +void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) { + OS << "seq_cst"; +} + template<typename T> void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { for (typename T::varlist_iterator I = Node->varlist_begin(), @@ -820,6 +836,11 @@ void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPForSimdDirective(OMPForSimdDirective *Node) { + Indent() << "#pragma omp for simd "; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPSectionsDirective(OMPSectionsDirective *Node) { Indent() << "#pragma omp sections "; PrintOMPExecutableDirective(Node); @@ -855,6 +876,12 @@ void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPParallelForSimdDirective( + OMPParallelForSimdDirective *Node) { + Indent() << "#pragma omp parallel for simd "; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPParallelSectionsDirective( OMPParallelSectionsDirective *Node) { Indent() << "#pragma omp parallel sections "; @@ -886,6 +913,26 @@ void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) { + Indent() << "#pragma omp ordered"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPAtomicDirective(OMPAtomicDirective *Node) { + Indent() << "#pragma omp atomic "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) { + Indent() << "#pragma omp target "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) { + Indent() << "#pragma omp teams "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// @@ -957,28 +1004,7 @@ void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) { } void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) { - switch (Node->getIdentType()) { - default: - llvm_unreachable("unknown case"); - case PredefinedExpr::Func: - OS << "__func__"; - break; - case PredefinedExpr::Function: - OS << "__FUNCTION__"; - break; - case PredefinedExpr::FuncDName: - OS << "__FUNCDNAME__"; - break; - case PredefinedExpr::FuncSig: - OS << "__FUNCSIG__"; - break; - case PredefinedExpr::LFunction: - OS << "L__FUNCTION__"; - break; - case PredefinedExpr::PrettyFunction: - OS << "__PRETTY_FUNCTION__"; - break; - } + OS << PredefinedExpr::getIdentTypeName(Node->getIdentType()); } void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { @@ -1716,6 +1742,8 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { case LCK_ByCopy: OS << C->getCapturedVar()->getName(); break; + case LCK_VLAType: + llvm_unreachable("VLA type in explicit captures."); } if (C->isInitCapture()) @@ -1994,6 +2022,20 @@ void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){ PrintExpr(Node->GetTemporaryExpr()); } +void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) { + OS << "("; + if (E->getLHS()) { + PrintExpr(E->getLHS()); + OS << " " << BinaryOperator::getOpcodeStr(E->getOperator()) << " "; + } + OS << "..."; + if (E->getRHS()) { + OS << " " << BinaryOperator::getOpcodeStr(E->getOperator()) << " "; + PrintExpr(E->getRHS()); + } + OS << ")"; +} + // Obj-C void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) { @@ -2138,6 +2180,11 @@ void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { PrintExpr(Node->getSourceExpr()); } +void StmtPrinter::VisitTypoExpr(TypoExpr *Node) { + // TODO: Print something reasonable for a TypoExpr, if necessary. + assert(false && "Cannot print TypoExpr nodes"); +} + void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { OS << "__builtin_astype("; PrintExpr(Node->getSrcExpr()); diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index f44f25c..d1f25d6 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -310,18 +310,38 @@ void OMPClauseProfiler::VisitOMPUntiedClause(const OMPUntiedClause *) {} void OMPClauseProfiler::VisitOMPMergeableClause(const OMPMergeableClause *) {} +void OMPClauseProfiler::VisitOMPReadClause(const OMPReadClause *) {} + +void OMPClauseProfiler::VisitOMPWriteClause(const OMPWriteClause *) {} + +void OMPClauseProfiler::VisitOMPUpdateClause(const OMPUpdateClause *) {} + +void OMPClauseProfiler::VisitOMPCaptureClause(const OMPCaptureClause *) {} + +void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {} + template<typename T> void OMPClauseProfiler::VisitOMPClauseList(T *Node) { - for (auto *I : Node->varlists()) - Profiler->VisitStmt(I); + for (auto *E : Node->varlists()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) { VisitOMPClauseList(C); + for (auto *E : C->private_copies()) { + Profiler->VisitStmt(E); + } } -void OMPClauseProfiler::VisitOMPFirstprivateClause( - const OMPFirstprivateClause *C) { +void +OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) { VisitOMPClauseList(C); + for (auto *E : C->private_copies()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->inits()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) { @@ -368,16 +388,24 @@ StmtProfiler::VisitOMPExecutableDirective(const OMPExecutableDirective *S) { P.Visit(*I); } +void StmtProfiler::VisitOMPLoopDirective(const OMPLoopDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPParallelDirective(const OMPParallelDirective *S) { VisitOMPExecutableDirective(S); } void StmtProfiler::VisitOMPSimdDirective(const OMPSimdDirective *S) { - VisitOMPExecutableDirective(S); + VisitOMPLoopDirective(S); } void StmtProfiler::VisitOMPForDirective(const OMPForDirective *S) { - VisitOMPExecutableDirective(S); + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPForSimdDirective(const OMPForSimdDirective *S) { + VisitOMPLoopDirective(S); } void StmtProfiler::VisitOMPSectionsDirective(const OMPSectionsDirective *S) { @@ -403,7 +431,12 @@ void StmtProfiler::VisitOMPCriticalDirective(const OMPCriticalDirective *S) { void StmtProfiler::VisitOMPParallelForDirective(const OMPParallelForDirective *S) { - VisitOMPExecutableDirective(S); + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPParallelForSimdDirective( + const OMPParallelForSimdDirective *S) { + VisitOMPLoopDirective(S); } void StmtProfiler::VisitOMPParallelSectionsDirective( @@ -431,6 +464,22 @@ void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPOrderedDirective(const OMPOrderedDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPAtomicDirective(const OMPAtomicDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTargetDirective(const OMPTargetDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTeamsDirective(const OMPTeamsDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } @@ -452,6 +501,7 @@ void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) { void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) { VisitExpr(S); S->getValue().Profile(ID); + ID.AddInteger(S->getType()->castAs<BuiltinType>()->getKind()); } void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) { @@ -464,6 +514,7 @@ void StmtProfiler::VisitFloatingLiteral(const FloatingLiteral *S) { VisitExpr(S); S->getValue().Profile(ID); ID.AddBoolean(S->isExact()); + ID.AddInteger(S->getType()->castAs<BuiltinType>()->getKind()); } void StmtProfiler::VisitImaginaryLiteral(const ImaginaryLiteral *S) { @@ -1018,6 +1069,8 @@ StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) { VisitDecl(C->getCapturedVar()); ID.AddBoolean(C->isPackExpansion()); break; + case LCK_VLAType: + llvm_unreachable("VLA type in explicit captures."); } } // Note: If we actually needed to be able to match lambda @@ -1187,10 +1240,19 @@ void StmtProfiler::VisitMaterializeTemporaryExpr( VisitExpr(S); } +void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) { + VisitExpr(S); + ID.AddInteger(S->getOperator()); +} + void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) { VisitExpr(E); } +void StmtProfiler::VisitTypoExpr(const TypoExpr *E) { + VisitExpr(E); +} + void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) { VisitExpr(S); } diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index ac6a754..f8b73cb 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -33,11 +33,26 @@ using namespace clang; /// \param TemplArg the TemplateArgument instance to print. /// /// \param Out the raw_ostream instance to use for printing. +/// +/// \param Policy the printing policy for EnumConstantDecl printing. static void printIntegral(const TemplateArgument &TemplArg, - raw_ostream &Out) { + raw_ostream &Out, const PrintingPolicy& Policy) { const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); const llvm::APSInt &Val = TemplArg.getAsIntegral(); + if (const EnumType *ET = T->getAs<EnumType>()) { + for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) { + // In Sema::CheckTemplateArugment, enum template arguments value are + // extended to the size of the integer underlying the enum type. This + // may create a size difference between the enum value and template + // argument value, requiring isSameValue here instead of operator==. + if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) { + ECD->printQualifiedName(Out, Policy); + return; + } + } + } + if (T->isBooleanType()) { Out << (Val.getBoolValue() ? "true" : "false"); } else if (T->isCharType()) { @@ -90,7 +105,8 @@ bool TemplateArgument::isDependent() const { llvm_unreachable("Should not have a NULL template argument"); case Type: - return getAsType()->isDependentType(); + return getAsType()->isDependentType() || + isa<PackExpansionType>(getAsType()); case Template: return getAsTemplate().isDependent(); @@ -111,7 +127,8 @@ bool TemplateArgument::isDependent() const { return false; case Expression: - return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent()); + return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() || + isa<PackExpansionExpr>(getAsExpr())); case Pack: for (const auto &P : pack_elements()) @@ -294,8 +311,7 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { return TypeOrValue.V == Other.TypeOrValue.V; case Declaration: - return getAsDecl() == Other.getAsDecl() && - isDeclForReferenceParam() && Other.isDeclForReferenceParam(); + return getAsDecl() == Other.getAsDecl(); case Integral: return getIntegralType() == Other.getIntegralType() && @@ -377,7 +393,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, break; case Integral: { - printIntegral(*this, Out); + printIntegral(*this, Out, Policy); break; } diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 1677874..e4f364d 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -70,7 +70,7 @@ bool QualType::isConstant(QualType T, ASTContext &Ctx) { if (const ArrayType *AT = Ctx.getAsArrayType(T)) return AT->getElementType().isConstant(Ctx); - return false; + return T.getAddressSpace() == LangAS::opencl_constant; } unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context, @@ -378,9 +378,10 @@ bool Type::isInterfaceType() const { return false; } bool Type::isStructureOrClassType() const { - if (const RecordType *RT = getAs<RecordType>()) - return RT->getDecl()->isStruct() || RT->getDecl()->isClass() || - RT->getDecl()->isInterface(); + if (const RecordType *RT = getAs<RecordType>()) { + RecordDecl *RD = RT->getDecl(); + return RD->isStruct() || RD->isClass() || RD->isInterface(); + } return false; } bool Type::isVoidPointerType() const { @@ -540,10 +541,13 @@ const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const { } CXXRecordDecl *Type::getAsCXXRecordDecl() const { - if (const RecordType *RT = getAs<RecordType>()) - return dyn_cast<CXXRecordDecl>(RT->getDecl()); - else if (const InjectedClassNameType *Injected - = getAs<InjectedClassNameType>()) + return dyn_cast_or_null<CXXRecordDecl>(getAsTagDecl()); +} + +TagDecl *Type::getAsTagDecl() const { + if (const auto *TT = getAs<TagType>()) + return cast<TagDecl>(TT->getDecl()); + if (const auto *Injected = getAs<InjectedClassNameType>()) return Injected->getDecl(); return nullptr; @@ -1147,7 +1151,7 @@ bool Type::isLiteralType(const ASTContext &Ctx) const { // C++1y [basic.types]p10: // A type is a literal type if it is: // -- cv void; or - if (Ctx.getLangOpts().CPlusPlus1y && isVoidType()) + if (Ctx.getLangOpts().CPlusPlus14 && isVoidType()) return true; // C++11 [basic.types]p10: @@ -1577,6 +1581,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86FastCall: return "fastcall"; case CC_X86ThisCall: return "thiscall"; case CC_X86Pascal: return "pascal"; + case CC_X86VectorCall: return "vectorcall"; case CC_X86_64Win64: return "ms_abi"; case CC_X86_64SysV: return "sysv_abi"; case CC_AAPCS: return "aapcs"; @@ -1591,18 +1596,21 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, QualType canonical, const ExtProtoInfo &epi) - : FunctionType(FunctionProto, result, epi.TypeQuals, canonical, + : FunctionType(FunctionProto, result, canonical, result->isDependentType(), result->isInstantiationDependentType(), result->isVariablyModifiedType(), result->containsUnexpandedParameterPack(), epi.ExtInfo), - NumParams(params.size()), NumExceptions(epi.NumExceptions), - ExceptionSpecType(epi.ExceptionSpecType), + NumParams(params.size()), + NumExceptions(epi.ExceptionSpec.Exceptions.size()), + ExceptionSpecType(epi.ExceptionSpec.Type), HasAnyConsumedParams(epi.ConsumedParameters != nullptr), - Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn), - RefQualifier(epi.RefQualifier) { + Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) { assert(NumParams == params.size() && "function has too many parameters"); + FunctionTypeBits.TypeQuals = epi.TypeQuals; + FunctionTypeBits.RefQualifier = epi.RefQualifier; + // Fill in the trailing argument array. QualType *argSlot = reinterpret_cast<QualType*>(this+1); for (unsigned i = 0; i != NumParams; ++i) { @@ -1620,36 +1628,38 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, if (getExceptionSpecType() == EST_Dynamic) { // Fill in the exception array. QualType *exnSlot = argSlot + NumParams; - for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) { - if (epi.Exceptions[i]->isDependentType()) - setDependent(); - else if (epi.Exceptions[i]->isInstantiationDependentType()) + unsigned I = 0; + for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) { + // Note that a dependent exception specification does *not* make + // a type dependent; it's not even part of the C++ type system. + if (ExceptionType->isInstantiationDependentType()) setInstantiationDependent(); - - if (epi.Exceptions[i]->containsUnexpandedParameterPack()) + + if (ExceptionType->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - exnSlot[i] = epi.Exceptions[i]; + exnSlot[I++] = ExceptionType; } } else if (getExceptionSpecType() == EST_ComputedNoexcept) { // Store the noexcept expression and context. Expr **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams); - *noexSlot = epi.NoexceptExpr; - - if (epi.NoexceptExpr) { - if (epi.NoexceptExpr->isValueDependent() - || epi.NoexceptExpr->isTypeDependent()) - setDependent(); - else if (epi.NoexceptExpr->isInstantiationDependent()) + *noexSlot = epi.ExceptionSpec.NoexceptExpr; + + if (epi.ExceptionSpec.NoexceptExpr) { + if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() || + epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent()) setInstantiationDependent(); + + if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack()) + setContainsUnexpandedParameterPack(); } } else if (getExceptionSpecType() == EST_Uninstantiated) { // Store the function decl from which we will resolve our // exception specification. FunctionDecl **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams); - slot[0] = epi.ExceptionSpecDecl; - slot[1] = epi.ExceptionSpecTemplate; + slot[0] = epi.ExceptionSpec.SourceDecl; + slot[1] = epi.ExceptionSpec.SourceTemplate; // This exception specification doesn't make the type dependent, because // it's not instantiated as part of instantiating the type. } else if (getExceptionSpecType() == EST_Unevaluated) { @@ -1657,7 +1667,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, // exception specification. FunctionDecl **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams); - slot[0] = epi.ExceptionSpecDecl; + slot[0] = epi.ExceptionSpec.SourceDecl; } if (epi.ConsumedParameters) { @@ -1667,6 +1677,18 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, } } +bool FunctionProtoType::hasDependentExceptionSpec() const { + if (Expr *NE = getNoexceptExpr()) + return NE->isValueDependent(); + for (QualType ET : exceptions()) + // A pack expansion with a non-dependent pattern is still dependent, + // because we don't know whether the pattern is in the exception spec + // or not (that depends on whether the pack has 0 expansions). + if (ET->isDependentType() || ET->getAs<PackExpansionType>()) + return true; + return false; +} + FunctionProtoType::NoexceptResult FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const { ExceptionSpecificationType est = getExceptionSpecType(); @@ -1755,20 +1777,21 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, assert(!(unsigned(epi.Variadic) & ~1) && !(unsigned(epi.TypeQuals) & ~255) && !(unsigned(epi.RefQualifier) & ~3) && - !(unsigned(epi.ExceptionSpecType) & ~7) && + !(unsigned(epi.ExceptionSpec.Type) & ~15) && "Values larger than expected."); ID.AddInteger(unsigned(epi.Variadic) + (epi.TypeQuals << 1) + (epi.RefQualifier << 9) + - (epi.ExceptionSpecType << 11)); - if (epi.ExceptionSpecType == EST_Dynamic) { - for (unsigned i = 0; i != epi.NumExceptions; ++i) - ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr()); - } else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){ - epi.NoexceptExpr->Profile(ID, Context, false); - } else if (epi.ExceptionSpecType == EST_Uninstantiated || - epi.ExceptionSpecType == EST_Unevaluated) { - ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl()); + (epi.ExceptionSpec.Type << 11)); + if (epi.ExceptionSpec.Type == EST_Dynamic) { + for (QualType Ex : epi.ExceptionSpec.Exceptions) + ID.AddPointer(Ex.getAsOpaquePtr()); + } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept && + epi.ExceptionSpec.NoexceptExpr) { + epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, false); + } else if (epi.ExceptionSpec.Type == EST_Uninstantiated || + epi.ExceptionSpec.Type == EST_Unevaluated) { + ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl()); } if (epi.ConsumedParameters) { for (unsigned i = 0; i != NumParams; ++i) @@ -1909,6 +1932,7 @@ bool AttributedType::isCallingConv() const { case attr_fastcall: case attr_stdcall: case attr_thiscall: + case attr_vectorcall: case attr_pascal: case attr_ms_abi: case attr_sysv_abi: @@ -1976,32 +2000,14 @@ anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N, return false; } -#ifndef NDEBUG -static bool -anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N, - bool &InstantiationDependent) { - for (unsigned i = 0; i != N; ++i) { - if (Args[i].isDependent()) { - InstantiationDependent = true; - return true; - } - - if (Args[i].isInstantiationDependent()) - InstantiationDependent = true; - } - return false; -} -#endif - TemplateSpecializationType:: TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, QualType Canon, QualType AliasedType) : Type(TemplateSpecialization, Canon.isNull()? QualType(this, 0) : Canon, - Canon.isNull()? T.isDependent() : Canon->isDependentType(), - Canon.isNull()? T.isDependent() - : Canon->isInstantiationDependentType(), + Canon.isNull()? true : Canon->isDependentType(), + Canon.isNull()? true : Canon->isInstantiationDependentType(), false, T.containsUnexpandedParameterPack()), Template(T), NumArgs(NumArgs), TypeAlias(!AliasedType.isNull()) { @@ -2011,18 +2017,11 @@ TemplateSpecializationType(TemplateName T, T.getKind() == TemplateName::SubstTemplateTemplateParm || T.getKind() == TemplateName::SubstTemplateTemplateParmPack) && "Unexpected template name for TemplateSpecializationType"); - bool InstantiationDependent; - (void)InstantiationDependent; - assert((!Canon.isNull() || - T.isDependent() || - ::anyDependentTemplateArguments(Args, NumArgs, - InstantiationDependent)) && - "No canonical type for non-dependent class template specialization"); TemplateArgument *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1); for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - // Update dependent and variably-modified bits. + // Update instantiation-dependent and variably-modified bits. // If the canonical type exists and is non-dependent, the template // specialization type can be non-dependent even if one of the type // arguments is. Given: @@ -2030,17 +2029,13 @@ TemplateSpecializationType(TemplateName T, // U<T> is always non-dependent, irrespective of the type T. // However, U<Ts> contains an unexpanded parameter pack, even though // its expansion (and thus its desugared type) doesn't. - if (Canon.isNull() && Args[Arg].isDependent()) - setDependent(); - else if (Args[Arg].isInstantiationDependent()) + if (Args[Arg].isInstantiationDependent()) setInstantiationDependent(); - if (Args[Arg].getKind() == TemplateArgument::Type && Args[Arg].getAsType()->isVariablyModifiedType()) setVariablyModified(); if (Args[Arg].containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]); } diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 208d695..c069eb0 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -312,6 +312,14 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { return TL; } +void TypeOfTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> + ::initializeLocal(Context, Loc); + this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo( + getUnderlyingType(), Loc); +} + void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { setElaboratedKeywordLoc(Loc); diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index 061473e..e36fc17 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -673,6 +673,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_X86ThisCall: OS << " __attribute__((thiscall))"; break; + case CC_X86VectorCall: + OS << " __attribute__((vectorcall))"; + break; case CC_X86Pascal: OS << " __attribute__((pascal))"; break; @@ -1235,6 +1238,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case AttributedType::attr_fastcall: OS << "fastcall"; break; case AttributedType::attr_stdcall: OS << "stdcall"; break; case AttributedType::attr_thiscall: OS << "thiscall"; break; + case AttributedType::attr_vectorcall: OS << "vectorcall"; break; case AttributedType::attr_pascal: OS << "pascal"; break; case AttributedType::attr_ms_abi: OS << "ms_abi"; break; case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break; @@ -1428,18 +1432,6 @@ PrintTemplateArgumentList(raw_ostream &OS, OS << '>'; } -void QualType::dump(const char *msg) const { - if (msg) - llvm::errs() << msg << ": "; - LangOptions LO; - print(llvm::errs(), PrintingPolicy(LO), "identifier"); - llvm::errs() << '\n'; -} - -LLVM_DUMP_METHOD void QualType::dump() const { dump(nullptr); } - -LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); } - std::string Qualifiers::getAsString() const { LangOptions LO; return getAsString(PrintingPolicy(LO)); @@ -1498,6 +1490,9 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, case LangAS::opencl_constant: OS << "__constant"; break; + case LangAS::opencl_generic: + OS << "__generic"; + break; default: OS << "__attribute__((address_space("; OS << addrspace; diff --git a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp index c213d1c..53461eb 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp @@ -105,7 +105,7 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, CharUnits BaseOffset; if (I.isVirtual()) { // Ignore virtual bases that we've already visited. - if (!VBases.insert(BaseDecl)) + if (!VBases.insert(BaseDecl).second) continue; BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); @@ -157,7 +157,7 @@ void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, // Check if this is a virtual base. if (I.isVirtual()) { // Check if we've seen this base before. - if (!VBases.insert(BaseDecl)) + if (!VBases.insert(BaseDecl).second) continue; CharUnits BaseOffset = diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp index fa1127f..ddb1f05 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp @@ -64,7 +64,7 @@ public: /// Method - The method decl of the overrider. const CXXMethodDecl *Method; - /// VirtualBase - The virtual base class subobject of this overridder. + /// VirtualBase - The virtual base class subobject of this overrider. /// Note that this records the closest derived virtual base class subobject. const CXXRecordDecl *VirtualBase; @@ -389,7 +389,7 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base, CharUnits BaseOffset; if (B.isVirtual()) { - if (!VisitedVirtualBases.insert(BaseDecl)) { + if (!VisitedVirtualBases.insert(BaseDecl).second) { // We've visited this base before. continue; } @@ -748,7 +748,7 @@ VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); // Check if this is a virtual base that we haven't visited before. - if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl)) { + if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) { CharUnits Offset = LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass; @@ -1105,7 +1105,7 @@ namespace { bool visit(const CXXMethodDecl *MD) { // Don't recurse on this method if we've already collected it. - return Methods->insert(MD); + return Methods->insert(MD).second; } }; } @@ -1842,7 +1842,7 @@ void ItaniumVTableBuilder::DeterminePrimaryVirtualBases( CharUnits BaseOffsetInLayoutClass; if (B.isVirtual()) { - if (!VBases.insert(BaseDecl)) + if (!VBases.insert(BaseDecl).second) continue; const ASTRecordLayout &LayoutClassLayout = @@ -1870,8 +1870,9 @@ void ItaniumVTableBuilder::LayoutVTablesForVirtualBases( // 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 (B.isVirtual() && BaseDecl->isDynamicClass() && - !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) { + if (B.isVirtual() && BaseDecl->isDynamicClass() && + !PrimaryVirtualBases.count(BaseDecl) && + VBases.insert(BaseDecl).second) { const ASTRecordLayout &MostDerivedClassLayout = Context.getASTRecordLayout(MostDerivedClass); CharUnits BaseOffset = @@ -2390,6 +2391,7 @@ namespace { // first vfptr whose table provides a compatible overridden method. In many // cases, this permits the original vf-table entry to directly call // the method instead of passing through a thunk. +// See example before VFTableBuilder::ComputeThisOffset below. // // A compatible overridden method is one which does not have a non-trivial // covariant-return adjustment. @@ -2412,6 +2414,9 @@ namespace { // a) a user-defined ctor/dtor // and // b) a method overriding a method in a virtual base. +// +// To get a better understanding of this code, +// you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp class VFTableBuilder { public: @@ -2464,11 +2469,18 @@ private: /// or used for vcalls in the most derived class. bool Shadowed; - MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex) + /// UsesExtraSlot - Indicates if this vftable slot was created because + /// any of the overridden slots required a return adjusting thunk. + bool UsesExtraSlot; + + MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex, + bool UsesExtraSlot = false) : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex), - Shadowed(false) {} + Shadowed(false), UsesExtraSlot(UsesExtraSlot) {} - MethodInfo() : VBTableIndex(0), VFTableIndex(0), Shadowed(false) {} + MethodInfo() + : VBTableIndex(0), VFTableIndex(0), Shadowed(false), + UsesExtraSlot(false) {} }; typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy; @@ -2525,8 +2537,6 @@ private: } } - bool NeedsReturnAdjustingThunk(const CXXMethodDecl *MD); - /// AddMethods - Add the methods of this base subobject and the relevant /// subbases to the vftable we're currently laying out. void AddMethods(BaseSubobject Base, unsigned BaseDepth, @@ -2534,13 +2544,15 @@ private: BasesSetVectorTy &VisitedBases); void LayoutVFTable() { - // FIXME: add support for RTTI when we have proper LLVM support for symbols - // pointing to the middle of a section. + // RTTI data goes before all other entries. + if (HasRTTIComponent) + Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass)); BasesSetVectorTy VisitedBases; AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr, VisitedBases); - assert(Components.size() && "vftable can't be empty"); + assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) && + "vftable can't be empty"); assert(MethodVFTableLocations.empty()); for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(), @@ -2561,13 +2573,6 @@ private: } } - void ErrorUnsupported(StringRef Feature, SourceLocation Location) { - clang::DiagnosticsEngine &Diags = Context.getDiagnostics(); - unsigned DiagID = Diags.getCustomDiagID( - DiagnosticsEngine::Error, "v-table layout for %0 is not supported yet"); - Diags.Report(Context.getFullLoc(Location), DiagID) << Feature; - } - public: VFTableBuilder(MicrosoftVTableContext &VTables, const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which) @@ -2581,8 +2586,6 @@ public: // definition of the vftable. HasRTTIComponent = Context.getLangOpts().RTTIData && !MostDerivedClass->hasAttr<DLLImportAttr>(); - if (HasRTTIComponent) - Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass)); LayoutVFTable(); @@ -2634,7 +2637,7 @@ struct InitialOverriddenDefinitionCollector { if (OverriddenMD->size_overridden_methods() == 0) Bases.insert(OverriddenMD->getParent()); // Don't recurse on this method if we've already collected it. - return VisitedOverriddenMethods.insert(OverriddenMD); + return VisitedOverriddenMethods.insert(OverriddenMD).second; } }; @@ -2644,6 +2647,60 @@ static bool BaseInSet(const CXXBaseSpecifier *Specifier, return Bases->count(Specifier->getType()->getAsCXXRecordDecl()); } +// Let's study one class hierarchy as an example: +// struct A { +// virtual void f(); +// int x; +// }; +// +// struct B : virtual A { +// virtual void f(); +// }; +// +// Record layouts: +// struct A: +// 0 | (A vftable pointer) +// 4 | int x +// +// struct B: +// 0 | (B vbtable pointer) +// 4 | struct A (virtual base) +// 4 | (A vftable pointer) +// 8 | int x +// +// Let's assume we have a pointer to the A part of an object of dynamic type B: +// B b; +// A *a = (A*)&b; +// a->f(); +// +// In this hierarchy, f() belongs to the vftable of A, so B::f() expects +// "this" parameter to point at the A subobject, which is B+4. +// In the B::f() prologue, it adjusts "this" back to B by subtracting 4, +// performed as a *static* adjustment. +// +// Interesting thing happens when we alter the relative placement of A and B +// subobjects in a class: +// struct C : virtual B { }; +// +// C c; +// A *a = (A*)&c; +// a->f(); +// +// Respective record layout is: +// 0 | (C vbtable pointer) +// 4 | struct A (virtual base) +// 4 | (A vftable pointer) +// 8 | int x +// 12 | struct B (virtual base) +// 12 | (B vbtable pointer) +// +// The final overrider of f() in class C is still B::f(), so B+4 should be +// passed as "this" to that code. However, "a" points at B-8, so the respective +// vftable entry should hold a thunk that adds 12 to the "this" argument before +// performing a tail call to B::f(). +// +// With this example in mind, we can now calculate the 'this' argument offset +// for the given method, relative to the beginning of the MostDerivedClass. CharUnits VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) { InitialOverriddenDefinitionCollector Collector; @@ -2723,6 +2780,104 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) { return Ret; } +// Things are getting even more complex when the "this" adjustment has to +// use a dynamic offset instead of a static one, or even two dynamic offsets. +// This is sometimes required when a virtual call happens in the middle of +// a non-most-derived class construction or destruction. +// +// Let's take a look at the following example: +// struct A { +// virtual void f(); +// }; +// +// void foo(A *a) { a->f(); } // Knows nothing about siblings of A. +// +// struct B : virtual A { +// virtual void f(); +// B() { +// foo(this); +// } +// }; +// +// struct C : virtual B { +// virtual void f(); +// }; +// +// Record layouts for these classes are: +// struct A +// 0 | (A vftable pointer) +// +// struct B +// 0 | (B vbtable pointer) +// 4 | (vtordisp for vbase A) +// 8 | struct A (virtual base) +// 8 | (A vftable pointer) +// +// struct C +// 0 | (C vbtable pointer) +// 4 | (vtordisp for vbase A) +// 8 | struct A (virtual base) // A precedes B! +// 8 | (A vftable pointer) +// 12 | struct B (virtual base) +// 12 | (B vbtable pointer) +// +// When one creates an object of type C, the C constructor: +// - initializes all the vbptrs, then +// - calls the A subobject constructor +// (initializes A's vfptr with an address of A vftable), then +// - calls the B subobject constructor +// (initializes A's vfptr with an address of B vftable and vtordisp for A), +// that in turn calls foo(), then +// - initializes A's vfptr with an address of C vftable and zeroes out the +// vtordisp +// FIXME: if a structor knows it belongs to MDC, why doesn't it use a vftable +// without vtordisp thunks? +// FIXME: how are vtordisp handled in the presence of nooverride/final? +// +// When foo() is called, an object with a layout of class C has a vftable +// referencing B::f() that assumes a B layout, so the "this" adjustments are +// incorrect, unless an extra adjustment is done. This adjustment is called +// "vtordisp adjustment". Vtordisp basically holds the difference between the +// actual location of a vbase in the layout class and the location assumed by +// the vftable of the class being constructed/destructed. Vtordisp is only +// needed if "this" escapes a +// structor (or we can't prove otherwise). +// [i.e. vtordisp is a dynamic adjustment for a static adjustment, which is an +// estimation of a dynamic adjustment] +// +// foo() gets a pointer to the A vbase and doesn't know anything about B or C, +// so it just passes that pointer as "this" in a virtual call. +// If there was no vtordisp, that would just dispatch to B::f(). +// However, B::f() assumes B+8 is passed as "this", +// yet the pointer foo() passes along is B-4 (i.e. C+8). +// An extra adjustment is needed, so we emit a thunk into the B vftable. +// This vtordisp thunk subtracts the value of vtordisp +// from the "this" argument (-12) before making a tailcall to B::f(). +// +// Let's consider an even more complex example: +// struct D : virtual B, virtual C { +// D() { +// foo(this); +// } +// }; +// +// struct D +// 0 | (D vbtable pointer) +// 4 | (vtordisp for vbase A) +// 8 | struct A (virtual base) // A precedes both B and C! +// 8 | (A vftable pointer) +// 12 | struct B (virtual base) // B precedes C! +// 12 | (B vbtable pointer) +// 16 | struct C (virtual base) +// 16 | (C vbtable pointer) +// +// When D::D() calls foo(), we find ourselves in a thunk that should tailcall +// to C::f(), which assumes C+8 as its "this" parameter. This time, foo() +// passes along A, which is C-8. The A vtordisp holds +// "D.vbptr[index_of_A] - offset_of_A_in_D" +// and we statically know offset_of_A_in_D, so can get a pointer to D. +// When we know it, we can make an extra vbtable lookup to locate the C vbase +// and one extra static adjustment to calculate the expected value of C+8. void VFTableBuilder::CalculateVtordispAdjustment( FinalOverriders::OverriderInfo Overrider, CharUnits ThisOffset, ThisAdjustment &TA) { @@ -2740,9 +2895,9 @@ void VFTableBuilder::CalculateVtordispAdjustment( // OK, now we know we need to use a vtordisp thunk. // The implicit vtordisp field is located right before the vbase. - CharUnits VFPtrVBaseOffset = VBaseMapEntry->second.VBaseOffset; + CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset; TA.Virtual.Microsoft.VtordispOffset = - (VFPtrVBaseOffset - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4; + (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4; // A simple vtordisp thunk will suffice if the final overrider is defined // in either the most derived class or its non-virtual base. @@ -2753,7 +2908,7 @@ void VFTableBuilder::CalculateVtordispAdjustment( // Otherwise, we need to do use the dynamic offset of the final overrider // in order to get "this" adjustment right. TA.Virtual.Microsoft.VBPtrOffset = - (VFPtrVBaseOffset + WhichVFPtr.NonVirtualOffset - + (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset - MostDerivedClassLayout.getVBPtrOffset()).getQuantity(); TA.Virtual.Microsoft.VBOffsetOffset = Context.getTypeSizeInChars(Context.IntTy).getQuantity() * @@ -2789,24 +2944,6 @@ static void GroupNewVirtualOverloads( VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend()); } -/// We need a return adjusting thunk for this method if its return type is -/// not trivially convertible to the return type of any of its overridden -/// methods. -bool VFTableBuilder::NeedsReturnAdjustingThunk(const CXXMethodDecl *MD) { - OverriddenMethodsSetTy OverriddenMethods; - ComputeAllOverriddenMethods(MD, OverriddenMethods); - for (OverriddenMethodsSetTy::iterator I = OverriddenMethods.begin(), - E = OverriddenMethods.end(); - I != E; ++I) { - const CXXMethodDecl *OverriddenMD = *I; - BaseOffset Adjustment = - ComputeReturnAdjustmentBaseOffset(Context, MD, OverriddenMD); - if (!Adjustment.isEmpty()) - return true; - } - return false; -} - static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) { for (const auto &B : RD->bases()) { if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base) @@ -2866,20 +3003,21 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, for (unsigned I = 0, E = VirtualMethods.size(); I != E; ++I) { const CXXMethodDecl *MD = VirtualMethods[I]; - FinalOverriders::OverriderInfo Overrider = + FinalOverriders::OverriderInfo FinalOverrider = Overriders.getOverrider(MD, Base.getBaseOffset()); - const CXXMethodDecl *OverriderMD = Overrider.Method; + const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method; const CXXMethodDecl *OverriddenMD = FindNearestOverriddenMethod(MD, VisitedBases); ThisAdjustment ThisAdjustmentOffset; - bool ReturnAdjustingThunk = false; - CharUnits ThisOffset = ComputeThisOffset(Overrider); + bool ReturnAdjustingThunk = false, ForceReturnAdjustmentMangling = false; + CharUnits ThisOffset = ComputeThisOffset(FinalOverrider); ThisAdjustmentOffset.NonVirtual = (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity(); - if ((OverriddenMD || OverriderMD != MD) && + if ((OverriddenMD || FinalOverriderMD != MD) && WhichVFPtr.getVBaseWithVPtr()) - CalculateVtordispAdjustment(Overrider, ThisOffset, ThisAdjustmentOffset); + CalculateVtordispAdjustment(FinalOverrider, ThisOffset, + ThisAdjustmentOffset); if (OverriddenMD) { // If MD overrides anything in this vftable, we need to update the entries. @@ -2892,7 +3030,16 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second; - if (!NeedsReturnAdjustingThunk(MD)) { + // Let's check if the overrider requires any return adjustments. + // We must create a new slot if the MD's return type is not trivially + // convertible to the OverriddenMD's one. + // Once a chain of method overrides adds a return adjusting vftable slot, + // all subsequent overrides will also use an extra method slot. + ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset( + Context, MD, OverriddenMD).isEmpty() || + OverriddenMethodInfo.UsesExtraSlot; + + if (!ReturnAdjustingThunk) { // No return adjustment needed - just replace the overridden method info // with the current info. MethodInfo MI(OverriddenMethodInfo.VBTableIndex, @@ -2911,8 +3058,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // Force a special name mangling for a return-adjusting thunk // unless the method is the final overrider without this adjustment. - ReturnAdjustingThunk = - !(MD == OverriderMD && ThisAdjustmentOffset.isEmpty()); + ForceReturnAdjustmentMangling = + !(MD == FinalOverriderMD && ThisAdjustmentOffset.isEmpty()); } else if (Base.getBaseOffset() != WhichVFPtr.FullOffsetInMDC || MD->size_overridden_methods()) { // Skip methods that don't belong to the vftable of the current class, @@ -2926,7 +3073,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, unsigned VBIndex = LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0; MethodInfo MI(VBIndex, - HasRTTIComponent ? Components.size() - 1 : Components.size()); + HasRTTIComponent ? Components.size() - 1 : Components.size(), + ReturnAdjustingThunk); assert(!MethodInfoMap.count(MD) && "Should not have method info for this method yet!"); @@ -2936,12 +3084,12 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // We don't want to do this for pure virtual member functions. BaseOffset ReturnAdjustmentOffset; ReturnAdjustment ReturnAdjustment; - if (!OverriderMD->isPure()) { + if (!FinalOverriderMD->isPure()) { ReturnAdjustmentOffset = - ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD); + ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD); } if (!ReturnAdjustmentOffset.isEmpty()) { - ReturnAdjustingThunk = true; + ForceReturnAdjustmentMangling = true; ReturnAdjustment.NonVirtual = ReturnAdjustmentOffset.NonVirtualOffset.getQuantity(); if (ReturnAdjustmentOffset.VirtualBase) { @@ -2955,8 +3103,9 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, } } - AddMethod(OverriderMD, ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment, - ReturnAdjustingThunk ? MD : nullptr)); + AddMethod(FinalOverriderMD, + ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment, + ForceReturnAdjustmentMangling ? MD : nullptr)); } } @@ -3039,10 +3188,8 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { if (MD->isPure()) Out << " [pure]"; - if (MD->isDeleted()) { - ErrorUnsupported("deleted methods", MD->getLocation()); + if (MD->isDeleted()) Out << " [deleted]"; - } ThunkInfo Thunk = VTableThunks.lookup(I); if (!Thunk.isEmpty()) @@ -3131,7 +3278,7 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { } static bool setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &A, - const ArrayRef<const CXXRecordDecl *> &B) { + ArrayRef<const CXXRecordDecl *> B) { for (ArrayRef<const CXXRecordDecl *>::iterator I = B.begin(), E = B.end(); I != E; ++I) { if (A.count(*I)) @@ -3201,10 +3348,6 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, if (P->MangledPath.empty() || P->MangledPath.back() != Base) P->NextBaseToMangle = Base; - // Keep track of the full path. - // FIXME: Why do we need this? - P->PathToBaseWithVPtr.insert(P->PathToBaseWithVPtr.begin(), Base); - // Keep track of which vtable the derived class is going to extend with // new methods or bases. We append to either the vftable of our primary // base, or the first non-virtual base that has a vbtable. @@ -3292,6 +3435,58 @@ MicrosoftVTableContext::~MicrosoftVTableContext() { llvm::DeleteContainerSeconds(VBaseInfo); } +static bool +findPathForVPtr(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, + const CXXRecordDecl *RD, CharUnits Offset, + llvm::SmallPtrSetImpl<const CXXRecordDecl *> &VBasesSeen, + VPtrInfo::BasePath &FullPath, VPtrInfo *Info) { + if (RD == Info->BaseWithVPtr && Offset == Info->FullOffsetInMDC) { + Info->PathToBaseWithVPtr = FullPath; + return true; + } + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + // Recurse with non-virtual bases first. + // FIXME: Does this need to be in layout order? Virtual bases will be in base + // specifier order, which isn't necessarily layout order. + SmallVector<CXXBaseSpecifier, 4> Bases(RD->bases_begin(), RD->bases_end()); + std::stable_partition(Bases.begin(), Bases.end(), + [](CXXBaseSpecifier bs) { return !bs.isVirtual(); }); + + for (const auto &B : Bases) { + const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl(); + CharUnits NewOffset; + if (!B.isVirtual()) + NewOffset = Offset + Layout.getBaseClassOffset(Base); + else { + if (!VBasesSeen.insert(Base).second) + return false; + NewOffset = MostDerivedLayout.getVBaseClassOffset(Base); + } + FullPath.push_back(Base); + if (findPathForVPtr(Context, MostDerivedLayout, Base, NewOffset, VBasesSeen, + FullPath, Info)) + return true; + FullPath.pop_back(); + } + return false; +} + +static void computeFullPathsForVFTables(ASTContext &Context, + const CXXRecordDecl *RD, + VPtrInfoVector &Paths) { + llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen; + const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD); + VPtrInfo::BasePath FullPath; + for (VPtrInfo *Info : Paths) { + findPathForVPtr(Context, MostDerivedLayout, RD, CharUnits::Zero(), + VBasesSeen, FullPath, Info); + VBasesSeen.clear(); + FullPath.clear(); + } +} + void MicrosoftVTableContext::computeVTableRelatedInformation( const CXXRecordDecl *RD) { assert(RD->isDynamicClass()); @@ -3304,6 +3499,7 @@ void MicrosoftVTableContext::computeVTableRelatedInformation( VPtrInfoVector *VFPtrs = new VPtrInfoVector(); computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs); + computeFullPathsForVFTables(Context, RD, *VFPtrs); VFPtrLocations[RD] = VFPtrs; MethodVFTableLocationsTy NewMethodLocations; |