diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
32 files changed, 3141 insertions, 1175 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index c9fb80c..4a831d9 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -738,9 +738,9 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr), BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr), - FirstLocalImport(), LastLocalImport(), + FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr), SourceMgr(SM), LangOpts(LOpts), - SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFile, SM)), + SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(nullptr), Listener(nullptr), @@ -866,6 +866,38 @@ void ASTContext::PrintStats() const { BumpAlloc.PrintStats(); } +void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M, + bool NotifyListeners) { + if (NotifyListeners) + if (auto *Listener = getASTMutationListener()) + Listener->RedefinedHiddenDefinition(ND, M); + + if (getLangOpts().ModulesLocalVisibility) + MergedDefModules[ND].push_back(M); + else + ND->setHidden(false); +} + +void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) { + auto It = MergedDefModules.find(ND); + if (It == MergedDefModules.end()) + return; + + auto &Merged = It->second; + llvm::DenseSet<Module*> Found; + for (Module *&M : Merged) + if (!Found.insert(M).second) + M = nullptr; + Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end()); +} + +ExternCContextDecl *ASTContext::getExternCContextDecl() const { + if (!ExternCContext) + ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl()); + + return ExternCContext; +} + RecordDecl *ASTContext::buildImplicitRecord(StringRef Name, RecordDecl::TagKind TK) const { SourceLocation Loc; @@ -877,6 +909,8 @@ RecordDecl *ASTContext::buildImplicitRecord(StringRef Name, NewDecl = RecordDecl::Create(*this, TK, getTranslationUnitDecl(), Loc, Loc, &Idents.get(Name)); NewDecl->setImplicit(); + NewDecl->addAttr(TypeVisibilityAttr::CreateImplicit( + const_cast<ASTContext &>(*this), TypeVisibilityAttr::Default)); return NewDecl; } @@ -1326,7 +1360,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { } Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (VD->hasGlobalStorage()) + if (VD->hasGlobalStorage() && !ForAlignof) Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); } } @@ -1669,13 +1703,23 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; } - if (const EnumType *ET = dyn_cast<EnumType>(TT)) - return getTypeInfo(ET->getDecl()->getIntegerType()); + if (const EnumType *ET = dyn_cast<EnumType>(TT)) { + const EnumDecl *ED = ET->getDecl(); + TypeInfo Info = + getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType()); + if (unsigned AttrAlign = ED->getMaxAlignment()) { + Info.Align = AttrAlign; + Info.AlignIsRequired = true; + } + return Info; + } const RecordType *RT = cast<RecordType>(TT); - const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl()); + const RecordDecl *RD = RT->getDecl(); + const ASTRecordLayout &Layout = getASTRecordLayout(RD); Width = toBits(Layout.getSize()); Align = toBits(Layout.getAlignment()); + AlignIsRequired = RD->hasAttr<AlignedAttr>(); break; } @@ -1778,13 +1822,20 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { TypeInfo TI = getTypeInfo(T); unsigned ABIAlign = TI.Align; + T = T->getBaseElementTypeUnsafe(); + + // The preferred alignment of member pointers is that of a pointer. + if (T->isMemberPointerType()) + return getPreferredTypeAlign(getPointerDiffType().getTypePtr()); + if (Target->getTriple().getArch() == llvm::Triple::xcore) return ABIAlign; // Never overalign on XCore. // Double and long long should be naturally aligned if possible. - T = T->getBaseElementTypeUnsafe(); if (const ComplexType *CT = T->getAs<ComplexType>()) T = CT->getElementType().getTypePtr(); + if (const EnumType *ET = T->getAs<EnumType>()) + T = ET->getDecl()->getIntegerType().getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Double) || T->isSpecificBuiltinType(BuiltinType::LongLong) || T->isSpecificBuiltinType(BuiltinType::ULongLong)) @@ -1796,6 +1847,13 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { return ABIAlign; } +/// getTargetDefaultAlignForAttributeAligned - Return the default alignment +/// for __attribute__((aligned)) on this target, to be used if no alignment +/// value is specified. +unsigned ASTContext::getTargetDefaultAlignForAttributeAligned(void) const { + return getTargetInfo().getDefaultAlignForAttributeAligned(); +} + /// getAlignOfGlobalVar - Return the alignment in bits that should be given /// to a global variable of the specified type. unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { @@ -3337,7 +3395,7 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, (void)CheckT; } - T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon); + T = new (*this, TypeAlignment) ElaboratedType(Keyword, NNS, NamedType, Canon); Types.push_back(T); ElaboratedTypes.InsertNode(T, InsertPos); return QualType(T, 0); @@ -3361,7 +3419,7 @@ ASTContext::getParenType(QualType InnerType) const { (void)CheckT; } - T = new (*this) ParenType(InnerType, Canon); + T = new (*this, TypeAlignment) ParenType(InnerType, Canon); Types.push_back(T); ParenTypes.InsertNode(T, InsertPos); return QualType(T, 0); @@ -3390,7 +3448,7 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, if (T) return QualType(T, 0); - T = new (*this) DependentNameType(Keyword, NNS, Name, Canon); + T = new (*this, TypeAlignment) DependentNameType(Keyword, NNS, Name, Canon); Types.push_back(T); DependentNameTypes.InsertNode(T, InsertPos); return QualType(T, 0); @@ -3492,7 +3550,8 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, } } - T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions); + T = new (*this, TypeAlignment) + PackExpansionType(Pattern, Canon, NumExpansions); Types.push_back(T); PackExpansionTypes.InsertNode(T, InsertPos); return QualType(T, 0); @@ -3500,9 +3559,9 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, /// CmpProtocolNames - Comparison predicate for sorting protocols /// alphabetically. -static bool CmpProtocolNames(const ObjCProtocolDecl *LHS, - const ObjCProtocolDecl *RHS) { - return LHS->getDeclName() < RHS->getDeclName(); +static int CmpProtocolNames(ObjCProtocolDecl *const *LHS, + ObjCProtocolDecl *const *RHS) { + return DeclarationName::compare((*LHS)->getDeclName(), (*RHS)->getDeclName()); } static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols, @@ -3513,7 +3572,7 @@ static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols, return false; for (unsigned i = 1; i != NumProtocols; ++i) - if (!CmpProtocolNames(Protocols[i-1], Protocols[i]) || + if (CmpProtocolNames(&Protocols[i - 1], &Protocols[i]) >= 0 || Protocols[i]->getCanonicalDecl() != Protocols[i]) return false; return true; @@ -3524,7 +3583,7 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols; // Sort protocols, keyed by name. - std::sort(Protocols, Protocols+NumProtocols, CmpProtocolNames); + llvm::array_pod_sort(Protocols, ProtocolsEnd, CmpProtocolNames); // Canonicalize. for (unsigned I = 0, N = NumProtocols; I != N; ++I) @@ -4325,6 +4384,19 @@ QualType ASTContext::getSignatureParameterType(QualType T) const { return T.getUnqualifiedType(); } +QualType ASTContext::getExceptionObjectType(QualType T) const { + // C++ [except.throw]p3: + // A throw-expression initializes a temporary object, called the exception + // object, the type of which is determined by removing any top-level + // cv-qualifiers from the static type of the operand of throw and adjusting + // the type from "array of T" or "function returning T" to "pointer to T" + // or "pointer to function returning T", [...] + T = getVariableArrayDecayedType(T); + if (T->isArrayType() || T->isFunctionType()) + T = getDecayedType(T); + return T.getUnqualifiedType(); +} + /// getArrayDecayedType - Return the properly qualified result of decaying the /// specified array type to a pointer. This operation is non-trivial when /// handling typedefs etc. The canonical type of "T" must be an array type, @@ -4859,7 +4931,7 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const { bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const { return getLangOpts().MSVCCompat && VD->isStaticDataMember() && VD->getType()->isIntegralOrEnumerationType() && - !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit(); + VD->isFirstDecl() && !VD->isOutOfLine() && VD->hasInit(); } static inline @@ -7544,7 +7616,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, break; case 'U': assert(!Signed && "Can't use both 'S' and 'U' modifiers!"); - assert(!Unsigned && "Can't use 'S' modifier multiple times!"); + assert(!Unsigned && "Can't use 'U' modifier multiple times!"); Unsigned = true; break; case 'L': @@ -7579,7 +7651,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, break; case 'h': assert(HowLong == 0 && !Signed && !Unsigned && - "Bad modifiers used with 'f'!"); + "Bad modifiers used with 'h'!"); Type = Context.HalfTy; break; case 'f': @@ -7806,6 +7878,9 @@ QualType ASTContext::GetBuiltinType(unsigned Id, ArgTypes.push_back(Ty); } + if (Id == Builtin::BI__GetExceptionInfo) + return QualType(); + assert((TypeStr[0] != '.' || TypeStr[1] == 0) && "'.' should only occur at end of builtin type list!"); @@ -7909,7 +7984,7 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, while (LexicalContext && !isa<FunctionDecl>(LexicalContext)) LexicalContext = LexicalContext->getLexicalParent(); - // Let the static local variable inherit it's linkage from the nearest + // Let the static local variable inherit its linkage from the nearest // enclosing function. if (LexicalContext) StaticLocalLinkage = @@ -8042,7 +8117,9 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, if (IsCXXMethod) return ABI->getDefaultMethodCallConv(IsVariadic); - return (LangOpts.MRTD && !IsVariadic) ? CC_X86StdCall : CC_C; + if (LangOpts.MRTD && !IsVariadic) return CC_X86StdCall; + + return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); } bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { @@ -8161,6 +8238,31 @@ MangleNumberingContext *ASTContext::createMangleNumberingContext() const { return ABI->createMangleNumberingContext(); } +const CXXConstructorDecl * +ASTContext::getCopyConstructorForExceptionObject(CXXRecordDecl *RD) { + return ABI->getCopyConstructorForExceptionObject( + cast<CXXRecordDecl>(RD->getFirstDecl())); +} + +void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD, + CXXConstructorDecl *CD) { + return ABI->addCopyConstructorForExceptionObject( + cast<CXXRecordDecl>(RD->getFirstDecl()), + cast<CXXConstructorDecl>(CD->getFirstDecl())); +} + +void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx, Expr *DAE) { + ABI->addDefaultArgExprForConstructor( + cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE); +} + +Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx) { + return ABI->getDefaultArgExprForConstructor( + cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx); +} + void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { ParamIndices[D] = index; } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp index ebf5e65..60cbb06 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp @@ -508,6 +508,8 @@ namespace { void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node); void VisitCXXConstructExpr(const CXXConstructExpr *Node); void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); + void VisitCXXNewExpr(const CXXNewExpr *Node); + void VisitCXXDeleteExpr(const CXXDeleteExpr *Node); void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node); void VisitExprWithCleanups(const ExprWithCleanups *Node); void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node); @@ -516,6 +518,7 @@ namespace { VisitExpr(Node); dumpDecl(Node->getLambdaClass()); } + void VisitSizeOfPackExpr(const SizeOfPackExpr *Node); // ObjC void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); @@ -974,8 +977,10 @@ void ASTDumper::dumpDecl(const Decl *D) { dumpSourceRange(D->getSourceRange()); OS << ' '; dumpLocation(D->getLocation()); - if (Module *M = D->getOwningModule()) + if (Module *M = D->getImportedOwningModule()) OS << " in " << M->getFullModuleName(); + else if (Module *M = D->getLocalOwningModule()) + OS << " in (local) " << M->getFullModuleName(); if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) if (ND->isHidden()) OS << " hidden"; @@ -1099,10 +1104,13 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { E = D->getDeclsInPrototypeScope().end(); I != E; ++I) dumpDecl(*I); - for (FunctionDecl::param_const_iterator I = D->param_begin(), - E = D->param_end(); - I != E; ++I) - dumpDecl(*I); + if (!D->param_begin() && D->getNumParams()) + dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; }); + else + for (FunctionDecl::param_const_iterator I = D->param_begin(), + E = D->param_end(); + I != E; ++I) + dumpDecl(*I); if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D)) for (CXXConstructorDecl::init_const_iterator I = C->init_begin(), @@ -1913,6 +1921,32 @@ void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) { dumpCXXTemporary(Node->getTemporary()); } +void ASTDumper::VisitCXXNewExpr(const CXXNewExpr *Node) { + VisitExpr(Node); + if (Node->isGlobalNew()) + OS << " global"; + if (Node->isArray()) + OS << " array"; + if (Node->getOperatorNew()) { + OS << ' '; + dumpBareDeclRef(Node->getOperatorNew()); + } + // We could dump the deallocation function used in case of error, but it's + // usually not that interesting. +} + +void ASTDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) { + VisitExpr(Node); + if (Node->isGlobalDelete()) + OS << " global"; + if (Node->isArrayForm()) + OS << " array"; + if (Node->getOperatorDelete()) { + OS << ' '; + dumpBareDeclRef(Node->getOperatorDelete()); + } +} + void ASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) { VisitExpr(Node); @@ -1934,6 +1968,13 @@ void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) { OS << ")"; } +void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { + VisitExpr(Node); + dumpPointer(Node->getPack()); + dumpName(Node->getPack()); +} + + //===----------------------------------------------------------------------===// // Obj-C Expressions //===----------------------------------------------------------------------===// @@ -2255,6 +2296,11 @@ LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { P.dumpStmt(this); } +LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const { + ASTDumper P(OS, nullptr, nullptr); + P.dumpStmt(this); +} + LLVM_DUMP_METHOD void Stmt::dump() const { ASTDumper P(llvm::errs(), nullptr, nullptr); P.dumpStmt(this); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index 2442e8e..911f168 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -67,6 +67,7 @@ namespace clang { // FIXME: DependentDecltypeType QualType VisitRecordType(const RecordType *T); QualType VisitEnumType(const EnumType *T); + QualType VisitAttributedType(const AttributedType *T); // FIXME: TemplateTypeParmType // FIXME: SubstTemplateTypeParmType QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); @@ -80,7 +81,7 @@ namespace clang { // Importing declarations bool ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, - SourceLocation &Loc); + NamedDecl *&ToD, SourceLocation &Loc); void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr); void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); @@ -167,7 +168,44 @@ namespace clang { Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); // Importing statements + DeclGroupRef ImportDeclGroup(DeclGroupRef DG); + Stmt *VisitStmt(Stmt *S); + Stmt *VisitDeclStmt(DeclStmt *S); + Stmt *VisitNullStmt(NullStmt *S); + Stmt *VisitCompoundStmt(CompoundStmt *S); + Stmt *VisitCaseStmt(CaseStmt *S); + Stmt *VisitDefaultStmt(DefaultStmt *S); + Stmt *VisitLabelStmt(LabelStmt *S); + Stmt *VisitAttributedStmt(AttributedStmt *S); + Stmt *VisitIfStmt(IfStmt *S); + Stmt *VisitSwitchStmt(SwitchStmt *S); + Stmt *VisitWhileStmt(WhileStmt *S); + Stmt *VisitDoStmt(DoStmt *S); + Stmt *VisitForStmt(ForStmt *S); + Stmt *VisitGotoStmt(GotoStmt *S); + Stmt *VisitIndirectGotoStmt(IndirectGotoStmt *S); + Stmt *VisitContinueStmt(ContinueStmt *S); + Stmt *VisitBreakStmt(BreakStmt *S); + Stmt *VisitReturnStmt(ReturnStmt *S); + // FIXME: GCCAsmStmt + // FIXME: MSAsmStmt + // FIXME: SEHExceptStmt + // FIXME: SEHFinallyStmt + // FIXME: SEHTryStmt + // FIXME: SEHLeaveStmt + // FIXME: CapturedStmt + Stmt *VisitCXXCatchStmt(CXXCatchStmt *S); + Stmt *VisitCXXTryStmt(CXXTryStmt *S); + Stmt *VisitCXXForRangeStmt(CXXForRangeStmt *S); + // FIXME: MSDependentExistsStmt + Stmt *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); + Stmt *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); + Stmt *VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S); + Stmt *VisitObjCAtTryStmt(ObjCAtTryStmt *S); + Stmt *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); + Stmt *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); + Stmt *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); // Importing expressions Expr *VisitExpr(Expr *E); @@ -181,6 +219,9 @@ namespace clang { Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E); Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); Expr *VisitCStyleCastExpr(CStyleCastExpr *E); + Expr *VisitCXXConstructExpr(CXXConstructExpr *E); + Expr *VisitMemberExpr(MemberExpr *E); + Expr *VisitCallExpr(CallExpr *E); }; } using namespace clang; @@ -1724,6 +1765,27 @@ QualType ASTNodeImporter::VisitEnumType(const EnumType *T) { return Importer.getToContext().getTagDeclType(ToDecl); } +QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) { + QualType FromModifiedType = T->getModifiedType(); + QualType FromEquivalentType = T->getEquivalentType(); + QualType ToModifiedType; + QualType ToEquivalentType; + + if (!FromModifiedType.isNull()) { + ToModifiedType = Importer.Import(FromModifiedType); + if (ToModifiedType.isNull()) + return QualType(); + } + if (!FromEquivalentType.isNull()) { + ToEquivalentType = Importer.Import(FromEquivalentType); + if (ToEquivalentType.isNull()) + return QualType(); + } + + return Importer.getToContext().getAttributedType(T->getAttrKind(), + ToModifiedType, ToEquivalentType); +} + QualType ASTNodeImporter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { TemplateName ToTemplate = Importer.Import(T->getTemplateName()); @@ -1808,6 +1870,7 @@ ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, + NamedDecl *&ToD, SourceLocation &Loc) { // Import the context of this declaration. DC = Importer.ImportContext(D->getDeclContext()); @@ -1828,6 +1891,7 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC, // Import the location of this declaration. Loc = Importer.Import(D->getLocation()); + ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D)); return false; } @@ -2009,7 +2073,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To, ImportDefinitionKind Kind) { - if (To->getDefinition()) + if (To->getAnyInitializer()) return false; // FIXME: Can we really import any initializer? Alternatively, we could force @@ -2239,8 +2303,11 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; NamespaceDecl *MergeWithNamespace = nullptr; if (!Name) { @@ -2307,8 +2374,11 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // If this typedef is not in block scope, determine whether we've // seen a typedef with the same name (that we can merge with) or any @@ -2381,8 +2451,11 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Figure out what enum name we're looking for. unsigned IDNS = Decl::IDNS_Tag; @@ -2466,8 +2539,11 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Figure out what structure name we're looking for. unsigned IDNS = Decl::IDNS_Tag; @@ -2592,8 +2668,11 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; QualType T = Importer.Import(D->getType()); if (T.isNull()) @@ -2648,8 +2727,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. @@ -2741,10 +2823,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Create the imported function. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); FunctionDecl *ToFunction = nullptr; + SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart()); if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), - D->getInnerLocStart(), + InnerLocStart, NameInfo, T, TInfo, FromConstructor->isExplicit(), D->isInlineSpecified(), @@ -2753,7 +2836,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } else if (isa<CXXDestructorDecl>(D)) { ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), - D->getInnerLocStart(), + InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), D->isImplicit()); @@ -2761,7 +2844,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { = dyn_cast<CXXConversionDecl>(D)) { ToFunction = CXXConversionDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), - D->getInnerLocStart(), + InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), FromConversion->isExplicit(), @@ -2770,7 +2853,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { ToFunction = CXXMethodDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), - D->getInnerLocStart(), + InnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), Method->isInlineSpecified(), @@ -2778,7 +2861,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { Importer.Import(D->getLocEnd())); } else { ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, - D->getInnerLocStart(), + InnerLocStart, NameInfo, T, TInfo, D->getStorageClass(), D->isInlineSpecified(), D->hasWrittenPrototype(), @@ -2809,6 +2892,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setType(T); } + // Import the body, if any. + if (Stmt *FromBody = D->getBody()) { + if (Stmt *ToBody = Importer.Import(FromBody)) { + ToFunction->setBody(ToBody); + } + } + // FIXME: Other bits to merge? // Add this function to the lexical context. @@ -2855,8 +2945,11 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; @@ -2911,8 +3004,11 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; @@ -2978,8 +3074,11 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Determine whether we've already imported this ivar SmallVector<NamedDecl *, 2> FoundDecls; @@ -3028,8 +3127,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Try to find a variable in our own ("to") context with the same name and // in the same context as the variable we're importing. @@ -3137,6 +3239,10 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { Importer.Imported(D, ToVar); LexicalDC->addDeclInternal(ToVar); + if (!D->isFileVarDecl() && + D->isUsed()) + ToVar->setIsUsed(); + // Merge the initializer. if (ImportDefinition(D, ToVar)) return nullptr; @@ -3196,6 +3302,10 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { T, TInfo, D->getStorageClass(), /*FIXME: Default argument*/nullptr); ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); + + if (D->isUsed()) + ToParm->setIsUsed(); + return Importer.Imported(D, ToParm); } @@ -3204,8 +3314,11 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); @@ -3315,8 +3428,11 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; ObjCInterfaceDecl *ToInterface = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface())); @@ -3439,8 +3555,11 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; ObjCProtocolDecl *MergeWithProtocol = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; @@ -3614,8 +3733,11 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Look for an existing interface with the same name. ObjCInterfaceDecl *MergeWithIface = nullptr; @@ -3769,8 +3891,11 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // Check whether we have already imported this property. SmallVector<NamedDecl *, 2> FoundDecls; @@ -4000,8 +4125,11 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { @@ -4188,8 +4316,11 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return nullptr; + if (ToD) + return ToD; // We may already have a template of the same name; try to find and match it. assert(!DC->isFunctionOrMethod() && @@ -4371,10 +4502,457 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( // Import Statements //---------------------------------------------------------------------------- -Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { - Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node) - << S->getStmtClassName(); - return nullptr; +DeclGroupRef ASTNodeImporter::ImportDeclGroup(DeclGroupRef DG) { + if (DG.isNull()) + return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0); + size_t NumDecls = DG.end() - DG.begin(); + SmallVector<Decl *, 1> ToDecls(NumDecls); + auto &_Importer = this->Importer; + std::transform(DG.begin(), DG.end(), ToDecls.begin(), + [&_Importer](Decl *D) -> Decl * { + return _Importer.Import(D); + }); + return DeclGroupRef::Create(Importer.getToContext(), + ToDecls.begin(), + NumDecls); +} + + Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { + Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node) + << S->getStmtClassName(); + return nullptr; + } + +Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) { + DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup()); + for (Decl *ToD : ToDG) { + if (!ToD) + return nullptr; + } + SourceLocation ToStartLoc = Importer.Import(S->getStartLoc()); + SourceLocation ToEndLoc = Importer.Import(S->getEndLoc()); + return new (Importer.getToContext()) DeclStmt(ToDG, ToStartLoc, ToEndLoc); +} + +Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) { + SourceLocation ToSemiLoc = Importer.Import(S->getSemiLoc()); + return new (Importer.getToContext()) NullStmt(ToSemiLoc, + S->hasLeadingEmptyMacro()); +} + +Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { + SmallVector<Stmt *, 4> ToStmts(S->size()); + auto &_Importer = this->Importer; + std::transform(S->body_begin(), S->body_end(), ToStmts.begin(), + [&_Importer](Stmt *CS) -> Stmt * { + return _Importer.Import(CS); + }); + for (Stmt *ToS : ToStmts) { + if (!ToS) + return nullptr; + } + SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc()); + SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc()); + return new (Importer.getToContext()) CompoundStmt(Importer.getToContext(), + ToStmts, + ToLBraceLoc, ToRBraceLoc); +} + +Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { + Expr *ToLHS = Importer.Import(S->getLHS()); + if (!ToLHS) + return nullptr; + Expr *ToRHS = Importer.Import(S->getRHS()); + if (!ToRHS && S->getRHS()) + return nullptr; + SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc()); + SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc()); + SourceLocation ToColonLoc = Importer.Import(S->getColonLoc()); + return new (Importer.getToContext()) CaseStmt(ToLHS, ToRHS, + ToCaseLoc, ToEllipsisLoc, + ToColonLoc); +} + +Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) { + SourceLocation ToDefaultLoc = Importer.Import(S->getDefaultLoc()); + SourceLocation ToColonLoc = Importer.Import(S->getColonLoc()); + Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); + if (!ToSubStmt && S->getSubStmt()) + return nullptr; + return new (Importer.getToContext()) DefaultStmt(ToDefaultLoc, ToColonLoc, + ToSubStmt); +} + +Stmt *ASTNodeImporter::VisitLabelStmt(LabelStmt *S) { + SourceLocation ToIdentLoc = Importer.Import(S->getIdentLoc()); + LabelDecl *ToLabelDecl = + cast_or_null<LabelDecl>(Importer.Import(S->getDecl())); + if (!ToLabelDecl && S->getDecl()) + return nullptr; + Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); + if (!ToSubStmt && S->getSubStmt()) + return nullptr; + return new (Importer.getToContext()) LabelStmt(ToIdentLoc, ToLabelDecl, + ToSubStmt); +} + +Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) { + SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc()); + ArrayRef<const Attr*> FromAttrs(S->getAttrs()); + SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size()); + ASTContext &_ToContext = Importer.getToContext(); + std::transform(FromAttrs.begin(), FromAttrs.end(), ToAttrs.begin(), + [&_ToContext](const Attr *A) -> const Attr * { + return A->clone(_ToContext); + }); + for (const Attr *ToA : ToAttrs) { + if (!ToA) + return nullptr; + } + Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); + if (!ToSubStmt && S->getSubStmt()) + return nullptr; + return AttributedStmt::Create(Importer.getToContext(), ToAttrLoc, + ToAttrs, ToSubStmt); +} + +Stmt *ASTNodeImporter::VisitIfStmt(IfStmt *S) { + SourceLocation ToIfLoc = Importer.Import(S->getIfLoc()); + VarDecl *ToConditionVariable = nullptr; + if (VarDecl *FromConditionVariable = S->getConditionVariable()) { + ToConditionVariable = + dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable)); + if (!ToConditionVariable) + return nullptr; + } + Expr *ToCondition = Importer.Import(S->getCond()); + if (!ToCondition && S->getCond()) + return nullptr; + Stmt *ToThenStmt = Importer.Import(S->getThen()); + if (!ToThenStmt && S->getThen()) + return nullptr; + SourceLocation ToElseLoc = Importer.Import(S->getElseLoc()); + Stmt *ToElseStmt = Importer.Import(S->getElse()); + if (!ToElseStmt && S->getElse()) + return nullptr; + return new (Importer.getToContext()) IfStmt(Importer.getToContext(), + ToIfLoc, ToConditionVariable, + ToCondition, ToThenStmt, + ToElseLoc, ToElseStmt); +} + +Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { + VarDecl *ToConditionVariable = nullptr; + if (VarDecl *FromConditionVariable = S->getConditionVariable()) { + ToConditionVariable = + dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable)); + if (!ToConditionVariable) + return nullptr; + } + Expr *ToCondition = Importer.Import(S->getCond()); + if (!ToCondition && S->getCond()) + return nullptr; + SwitchStmt *ToStmt = new (Importer.getToContext()) SwitchStmt( + Importer.getToContext(), ToConditionVariable, + ToCondition); + Stmt *ToBody = Importer.Import(S->getBody()); + if (!ToBody && S->getBody()) + return nullptr; + ToStmt->setBody(ToBody); + ToStmt->setSwitchLoc(Importer.Import(S->getSwitchLoc())); + // Now we have to re-chain the cases. + SwitchCase *LastChainedSwitchCase = nullptr; + for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr; + SC = SC->getNextSwitchCase()) { + SwitchCase *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC)); + if (!ToSC) + return nullptr; + if (LastChainedSwitchCase) + LastChainedSwitchCase->setNextSwitchCase(ToSC); + else + ToStmt->setSwitchCaseList(ToSC); + LastChainedSwitchCase = ToSC; + } + return ToStmt; +} + +Stmt *ASTNodeImporter::VisitWhileStmt(WhileStmt *S) { + VarDecl *ToConditionVariable = nullptr; + if (VarDecl *FromConditionVariable = S->getConditionVariable()) { + ToConditionVariable = + dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable)); + if (!ToConditionVariable) + return nullptr; + } + Expr *ToCondition = Importer.Import(S->getCond()); + if (!ToCondition && S->getCond()) + return nullptr; + Stmt *ToBody = Importer.Import(S->getBody()); + if (!ToBody && S->getBody()) + return nullptr; + SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc()); + return new (Importer.getToContext()) WhileStmt(Importer.getToContext(), + ToConditionVariable, + ToCondition, ToBody, + ToWhileLoc); +} + +Stmt *ASTNodeImporter::VisitDoStmt(DoStmt *S) { + Stmt *ToBody = Importer.Import(S->getBody()); + if (!ToBody && S->getBody()) + return nullptr; + Expr *ToCondition = Importer.Import(S->getCond()); + if (!ToCondition && S->getCond()) + return nullptr; + SourceLocation ToDoLoc = Importer.Import(S->getDoLoc()); + SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc()); + SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc()); + return new (Importer.getToContext()) DoStmt(ToBody, ToCondition, + ToDoLoc, ToWhileLoc, + ToRParenLoc); +} + +Stmt *ASTNodeImporter::VisitForStmt(ForStmt *S) { + Stmt *ToInit = Importer.Import(S->getInit()); + if (!ToInit && S->getInit()) + return nullptr; + Expr *ToCondition = Importer.Import(S->getCond()); + if (!ToCondition && S->getCond()) + return nullptr; + VarDecl *ToConditionVariable = nullptr; + if (VarDecl *FromConditionVariable = S->getConditionVariable()) { + ToConditionVariable = + dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable)); + if (!ToConditionVariable) + return nullptr; + } + Expr *ToInc = Importer.Import(S->getInc()); + if (!ToInc && S->getInc()) + return nullptr; + Stmt *ToBody = Importer.Import(S->getBody()); + if (!ToBody && S->getBody()) + return nullptr; + SourceLocation ToForLoc = Importer.Import(S->getForLoc()); + SourceLocation ToLParenLoc = Importer.Import(S->getLParenLoc()); + SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc()); + return new (Importer.getToContext()) ForStmt(Importer.getToContext(), + ToInit, ToCondition, + ToConditionVariable, + ToInc, ToBody, + ToForLoc, ToLParenLoc, + ToRParenLoc); +} + +Stmt *ASTNodeImporter::VisitGotoStmt(GotoStmt *S) { + LabelDecl *ToLabel = nullptr; + if (LabelDecl *FromLabel = S->getLabel()) { + ToLabel = dyn_cast_or_null<LabelDecl>(Importer.Import(FromLabel)); + if (!ToLabel) + return nullptr; + } + SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc()); + SourceLocation ToLabelLoc = Importer.Import(S->getLabelLoc()); + return new (Importer.getToContext()) GotoStmt(ToLabel, + ToGotoLoc, ToLabelLoc); +} + +Stmt *ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { + SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc()); + SourceLocation ToStarLoc = Importer.Import(S->getStarLoc()); + Expr *ToTarget = Importer.Import(S->getTarget()); + if (!ToTarget && S->getTarget()) + return nullptr; + return new (Importer.getToContext()) IndirectGotoStmt(ToGotoLoc, ToStarLoc, + ToTarget); +} + +Stmt *ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) { + SourceLocation ToContinueLoc = Importer.Import(S->getContinueLoc()); + return new (Importer.getToContext()) ContinueStmt(ToContinueLoc); +} + +Stmt *ASTNodeImporter::VisitBreakStmt(BreakStmt *S) { + SourceLocation ToBreakLoc = Importer.Import(S->getBreakLoc()); + return new (Importer.getToContext()) BreakStmt(ToBreakLoc); +} + +Stmt *ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) { + SourceLocation ToRetLoc = Importer.Import(S->getReturnLoc()); + Expr *ToRetExpr = Importer.Import(S->getRetValue()); + if (!ToRetExpr && S->getRetValue()) + return nullptr; + VarDecl *NRVOCandidate = const_cast<VarDecl*>(S->getNRVOCandidate()); + VarDecl *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate)); + if (!ToNRVOCandidate && NRVOCandidate) + return nullptr; + return new (Importer.getToContext()) ReturnStmt(ToRetLoc, ToRetExpr, + ToNRVOCandidate); +} + +Stmt *ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) { + SourceLocation ToCatchLoc = Importer.Import(S->getCatchLoc()); + VarDecl *ToExceptionDecl = nullptr; + if (VarDecl *FromExceptionDecl = S->getExceptionDecl()) { + ToExceptionDecl = + dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl)); + if (!ToExceptionDecl) + return nullptr; + } + Stmt *ToHandlerBlock = Importer.Import(S->getHandlerBlock()); + if (!ToHandlerBlock && S->getHandlerBlock()) + return nullptr; + return new (Importer.getToContext()) CXXCatchStmt(ToCatchLoc, + ToExceptionDecl, + ToHandlerBlock); +} + +Stmt *ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) { + SourceLocation ToTryLoc = Importer.Import(S->getTryLoc()); + Stmt *ToTryBlock = Importer.Import(S->getTryBlock()); + if (!ToTryBlock && S->getTryBlock()) + return nullptr; + SmallVector<Stmt *, 1> ToHandlers(S->getNumHandlers()); + for (unsigned HI = 0, HE = S->getNumHandlers(); HI != HE; ++HI) { + CXXCatchStmt *FromHandler = S->getHandler(HI); + if (Stmt *ToHandler = Importer.Import(FromHandler)) + ToHandlers[HI] = ToHandler; + else + return nullptr; + } + return CXXTryStmt::Create(Importer.getToContext(), ToTryLoc, ToTryBlock, + ToHandlers); +} + +Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { + DeclStmt *ToRange = + dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt())); + if (!ToRange && S->getRangeStmt()) + return nullptr; + DeclStmt *ToBeginEnd = + dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginEndStmt())); + if (!ToBeginEnd && S->getBeginEndStmt()) + return nullptr; + Expr *ToCond = Importer.Import(S->getCond()); + if (!ToCond && S->getCond()) + return nullptr; + Expr *ToInc = Importer.Import(S->getInc()); + if (!ToInc && S->getInc()) + return nullptr; + DeclStmt *ToLoopVar = + dyn_cast_or_null<DeclStmt>(Importer.Import(S->getLoopVarStmt())); + if (!ToLoopVar && S->getLoopVarStmt()) + return nullptr; + Stmt *ToBody = Importer.Import(S->getBody()); + if (!ToBody && S->getBody()) + return nullptr; + SourceLocation ToForLoc = Importer.Import(S->getForLoc()); + SourceLocation ToColonLoc = Importer.Import(S->getColonLoc()); + SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc()); + return new (Importer.getToContext()) CXXForRangeStmt(ToRange, ToBeginEnd, + ToCond, ToInc, + ToLoopVar, ToBody, + ToForLoc, ToColonLoc, + ToRParenLoc); +} + +Stmt *ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { + Stmt *ToElem = Importer.Import(S->getElement()); + if (!ToElem && S->getElement()) + return nullptr; + Expr *ToCollect = Importer.Import(S->getCollection()); + if (!ToCollect && S->getCollection()) + return nullptr; + Stmt *ToBody = Importer.Import(S->getBody()); + if (!ToBody && S->getBody()) + return nullptr; + SourceLocation ToForLoc = Importer.Import(S->getForLoc()); + SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc()); + return new (Importer.getToContext()) ObjCForCollectionStmt(ToElem, + ToCollect, + ToBody, ToForLoc, + ToRParenLoc); +} + +Stmt *ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { + SourceLocation ToAtCatchLoc = Importer.Import(S->getAtCatchLoc()); + SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc()); + VarDecl *ToExceptionDecl = nullptr; + if (VarDecl *FromExceptionDecl = S->getCatchParamDecl()) { + ToExceptionDecl = + dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl)); + if (!ToExceptionDecl) + return nullptr; + } + Stmt *ToBody = Importer.Import(S->getCatchBody()); + if (!ToBody && S->getCatchBody()) + return nullptr; + return new (Importer.getToContext()) ObjCAtCatchStmt(ToAtCatchLoc, + ToRParenLoc, + ToExceptionDecl, + ToBody); +} + +Stmt *ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { + SourceLocation ToAtFinallyLoc = Importer.Import(S->getAtFinallyLoc()); + Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyBody()); + if (!ToAtFinallyStmt && S->getFinallyBody()) + return nullptr; + return new (Importer.getToContext()) ObjCAtFinallyStmt(ToAtFinallyLoc, + ToAtFinallyStmt); +} + +Stmt *ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { + SourceLocation ToAtTryLoc = Importer.Import(S->getAtTryLoc()); + Stmt *ToAtTryStmt = Importer.Import(S->getTryBody()); + if (!ToAtTryStmt && S->getTryBody()) + return nullptr; + SmallVector<Stmt *, 1> ToCatchStmts(S->getNumCatchStmts()); + for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) { + ObjCAtCatchStmt *FromCatchStmt = S->getCatchStmt(CI); + if (Stmt *ToCatchStmt = Importer.Import(FromCatchStmt)) + ToCatchStmts[CI] = ToCatchStmt; + else + return nullptr; + } + Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyStmt()); + if (!ToAtFinallyStmt && S->getFinallyStmt()) + return nullptr; + return ObjCAtTryStmt::Create(Importer.getToContext(), + ToAtTryLoc, ToAtTryStmt, + ToCatchStmts.begin(), ToCatchStmts.size(), + ToAtFinallyStmt); +} + +Stmt *ASTNodeImporter::VisitObjCAtSynchronizedStmt + (ObjCAtSynchronizedStmt *S) { + SourceLocation ToAtSynchronizedLoc = + Importer.Import(S->getAtSynchronizedLoc()); + Expr *ToSynchExpr = Importer.Import(S->getSynchExpr()); + if (!ToSynchExpr && S->getSynchExpr()) + return nullptr; + Stmt *ToSynchBody = Importer.Import(S->getSynchBody()); + if (!ToSynchBody && S->getSynchBody()) + return nullptr; + return new (Importer.getToContext()) ObjCAtSynchronizedStmt( + ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody); +} + +Stmt *ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { + SourceLocation ToAtThrowLoc = Importer.Import(S->getThrowLoc()); + Expr *ToThrow = Importer.Import(S->getThrowExpr()); + if (!ToThrow && S->getThrowExpr()) + return nullptr; + return new (Importer.getToContext()) ObjCAtThrowStmt(ToAtThrowLoc, ToThrow); +} + +Stmt *ASTNodeImporter::VisitObjCAutoreleasePoolStmt + (ObjCAutoreleasePoolStmt *S) { + SourceLocation ToAtLoc = Importer.Import(S->getAtLoc()); + Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); + if (!ToSubStmt && S->getSubStmt()) + return nullptr; + return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(ToAtLoc, + ToSubStmt); } //---------------------------------------------------------------------------- @@ -4585,6 +5163,107 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { Importer.Import(E->getRParenLoc())); } +Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + CXXConstructorDecl *ToCCD = + dyn_cast<CXXConstructorDecl>(Importer.Import(E->getConstructor())); + if (!ToCCD && E->getConstructor()) + return nullptr; + + size_t NumArgs = E->getNumArgs(); + SmallVector<Expr *, 1> ToArgs(NumArgs); + ASTImporter &_Importer = Importer; + std::transform(E->arg_begin(), E->arg_end(), ToArgs.begin(), + [&_Importer](Expr *AE) -> Expr * { + return _Importer.Import(AE); + }); + for (Expr *ToA : ToArgs) { + if (!ToA) + return nullptr; + } + + return CXXConstructExpr::Create(Importer.getToContext(), T, + Importer.Import(E->getLocation()), + ToCCD, E->isElidable(), + ToArgs, E->hadMultipleCandidates(), + E->isListInitialization(), + E->isStdInitListInitialization(), + E->requiresZeroInitialization(), + E->getConstructionKind(), + Importer.Import(E->getParenOrBraceRange())); +} + +Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToBase = Importer.Import(E->getBase()); + if (!ToBase && E->getBase()) + return nullptr; + + ValueDecl *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl())); + if (!ToMember && E->getMemberDecl()) + return nullptr; + + DeclAccessPair ToFoundDecl = DeclAccessPair::make( + dyn_cast<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())), + E->getFoundDecl().getAccess()); + + DeclarationNameInfo ToMemberNameInfo( + Importer.Import(E->getMemberNameInfo().getName()), + Importer.Import(E->getMemberNameInfo().getLoc())); + + if (E->hasExplicitTemplateArgs()) { + return nullptr; // FIXME: handle template arguments + } + + return MemberExpr::Create(Importer.getToContext(), ToBase, + E->isArrow(), + Importer.Import(E->getOperatorLoc()), + Importer.Import(E->getQualifierLoc()), + Importer.Import(E->getTemplateKeywordLoc()), + ToMember, ToFoundDecl, ToMemberNameInfo, + nullptr, T, E->getValueKind(), + E->getObjectKind()); +} + +Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToCallee = Importer.Import(E->getCallee()); + if (!ToCallee && E->getCallee()) + return nullptr; + + unsigned NumArgs = E->getNumArgs(); + + llvm::SmallVector<Expr *, 2> ToArgs(NumArgs); + + for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) { + Expr *FromArg = E->getArg(ai); + Expr *ToArg = Importer.Import(FromArg); + if (!ToArg) + return nullptr; + ToArgs[ai] = ToArg; + } + + Expr **ToArgs_Copied = new (Importer.getToContext()) + Expr*[NumArgs]; + + for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) + ToArgs_Copied[ai] = ToArgs[ai]; + + return new (Importer.getToContext()) + CallExpr(Importer.getToContext(), ToCallee, + ArrayRef<Expr*>(ToArgs_Copied, NumArgs), T, E->getValueKind(), + Importer.Import(E->getRParenLoc())); +} + ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTContext &FromContext, FileManager &FromFileManager, bool MinimalImport) @@ -4636,6 +5315,17 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { FromTSI->getTypeLoc().getLocStart()); } +Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) { + llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD); + if (Pos != ImportedDecls.end()) { + Decl *ToD = Pos->second; + ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD); + return ToD; + } else { + return nullptr; + } +} + Decl *ASTImporter::Import(Decl *FromD) { if (!FromD) return nullptr; @@ -4927,8 +5617,9 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) { FileID ToFileID = Import(Decomposed.first); if (ToFileID.isInvalid()) return SourceLocation(); - return ToSM.getLocForStartOfFile(ToFileID) - .getLocWithOffset(Decomposed.second); + SourceLocation ret = ToSM.getLocForStartOfFile(ToFileID) + .getLocWithOffset(Decomposed.second); + return ret; } SourceRange ASTImporter::Import(SourceRange FromRange) { @@ -4952,7 +5643,7 @@ FileID ASTImporter::Import(FileID FromID) { // Map the FileID for to the "to" source manager. FileID ToID; const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); - if (Cache->OrigEntry) { + if (Cache->OrigEntry && Cache->OrigEntry->getDir()) { // FIXME: We probably want to use getVirtualFile(), so we don't hit the // disk again // FIXME: We definitely want to re-use the existing MemoryBuffer, rather diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp index 0bf6bcd..cb60870 100644 --- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file contains out-of-line virtual methods for Attr classes. +// This file contains out-of-line methods for Attr classes. // //===----------------------------------------------------------------------===// @@ -18,10 +18,4 @@ #include "llvm/ADT/StringSwitch.h" using namespace clang; -Attr::~Attr() { } - -void InheritableAttr::anchor() { } - -void InheritableParamAttr::anchor() { } - #include "clang/AST/AttrImpl.inc" diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h index 8e9e358..dad2264 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h +++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h @@ -20,6 +20,8 @@ namespace clang { class ASTContext; +class CXXConstructorDecl; +class Expr; class MemberPointerType; class MangleNumberingContext; @@ -41,6 +43,20 @@ public: /// Returns a new mangling number context for this C++ ABI. virtual MangleNumberingContext *createMangleNumberingContext() const = 0; + + /// Adds a mapping from class to copy constructor for this C++ ABI. + virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *, + CXXConstructorDecl *) = 0; + + /// Retrieves the mapping from class to copy constructor for this C++ ABI. + virtual const CXXConstructorDecl * + getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0; + + virtual void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx, Expr *DAE) = 0; + + virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx) = 0; }; /// Creates an instance of a C++ ABI class. diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index 6e80ee7..800c8f8 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -318,48 +318,36 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, // // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy // way to make it any faster. - for (CXXBasePaths::paths_iterator P = Paths.begin(), PEnd = Paths.end(); - P != PEnd; /* increment in loop */) { - bool Hidden = false; - - for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end(); - PE != PEEnd && !Hidden; ++PE) { - if (PE->Base->isVirtual()) { - CXXRecordDecl *VBase = nullptr; - if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>()) - VBase = cast<CXXRecordDecl>(Record->getDecl()); - if (!VBase) + Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) { + for (const CXXBasePathElement &PE : Path) { + if (!PE.Base->isVirtual()) + continue; + + CXXRecordDecl *VBase = nullptr; + if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>()) + VBase = cast<CXXRecordDecl>(Record->getDecl()); + if (!VBase) + break; + + // The declaration(s) we found along this path were found in a + // subobject of a virtual base. Check whether this virtual + // base is a subobject of any other path; if so, then the + // declaration in this path are hidden by that patch. + for (const CXXBasePath &HidingP : Paths) { + CXXRecordDecl *HidingClass = nullptr; + if (const RecordType *Record = + HidingP.back().Base->getType()->getAs<RecordType>()) + HidingClass = cast<CXXRecordDecl>(Record->getDecl()); + if (!HidingClass) break; - // The declaration(s) we found along this path were found in a - // subobject of a virtual base. Check whether this virtual - // base is a subobject of any other path; if so, then the - // declaration in this path are hidden by that patch. - for (CXXBasePaths::paths_iterator HidingP = Paths.begin(), - HidingPEnd = Paths.end(); - HidingP != HidingPEnd; - ++HidingP) { - CXXRecordDecl *HidingClass = nullptr; - if (const RecordType *Record - = HidingP->back().Base->getType()->getAs<RecordType>()) - HidingClass = cast<CXXRecordDecl>(Record->getDecl()); - if (!HidingClass) - break; - - if (HidingClass->isVirtuallyDerivedFrom(VBase)) { - Hidden = true; - break; - } - } + if (HidingClass->isVirtuallyDerivedFrom(VBase)) + return true; } } + return false; + }); - if (Hidden) - P = Paths.Paths.erase(P); - else - ++P; - } - return true; } @@ -569,18 +557,14 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, // overrider. To do so, we dig down to the original virtual // functions using data recursion and update all of the methods it // overrides. - typedef std::pair<CXXMethodDecl::method_iterator, - CXXMethodDecl::method_iterator> OverriddenMethods; + typedef llvm::iterator_range<CXXMethodDecl::method_iterator> + OverriddenMethods; SmallVector<OverriddenMethods, 4> Stack; - Stack.push_back(std::make_pair(CanonM->begin_overridden_methods(), - CanonM->end_overridden_methods())); + Stack.push_back(llvm::make_range(CanonM->begin_overridden_methods(), + CanonM->end_overridden_methods())); while (!Stack.empty()) { - OverriddenMethods OverMethods = Stack.back(); - Stack.pop_back(); - - for (; OverMethods.first != OverMethods.second; ++OverMethods.first) { - const CXXMethodDecl *CanonOM - = cast<CXXMethodDecl>((*OverMethods.first)->getCanonicalDecl()); + for (const CXXMethodDecl *OM : Stack.pop_back_val()) { + const CXXMethodDecl *CanonOM = OM->getCanonicalDecl(); // C++ [class.virtual]p2: // A virtual member function C::vf of a class object S is @@ -601,8 +585,8 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, // Continue recursion to the methods that this virtual method // overrides. - Stack.push_back(std::make_pair(CanonOM->begin_overridden_methods(), - CanonOM->end_overridden_methods())); + Stack.push_back(llvm::make_range(CanonOM->begin_overridden_methods(), + CanonOM->end_overridden_methods())); } } @@ -630,54 +614,32 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { // Weed out any final overriders that come from virtual base class // subobjects that were hidden by other subobjects along any path. // This is the final-overrider variant of C++ [class.member.lookup]p10. - for (CXXFinalOverriderMap::iterator OM = FinalOverriders.begin(), - OMEnd = FinalOverriders.end(); - OM != OMEnd; - ++OM) { - for (OverridingMethods::iterator SO = OM->second.begin(), - SOEnd = OM->second.end(); - SO != SOEnd; - ++SO) { - SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO->second; + for (auto &OM : FinalOverriders) { + for (auto &SO : OM.second) { + SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO.second; if (Overriding.size() < 2) continue; - for (SmallVectorImpl<UniqueVirtualMethod>::iterator - Pos = Overriding.begin(), PosEnd = Overriding.end(); - Pos != PosEnd; - /* increment in loop */) { - if (!Pos->InVirtualSubobject) { - ++Pos; - continue; - } + auto IsHidden = [&Overriding](const UniqueVirtualMethod &M) { + if (!M.InVirtualSubobject) + return false; // We have an overriding method in a virtual base class // subobject (or non-virtual base class subobject thereof); // determine whether there exists an other overriding method // in a base class subobject that hides the virtual base class // subobject. - bool Hidden = false; - for (SmallVectorImpl<UniqueVirtualMethod>::iterator - OP = Overriding.begin(), OPEnd = Overriding.end(); - OP != OPEnd && !Hidden; - ++OP) { - if (Pos == OP) - continue; - - if (OP->Method->getParent()->isVirtuallyDerivedFrom( - const_cast<CXXRecordDecl *>(Pos->InVirtualSubobject))) - Hidden = true; - } - - if (Hidden) { - // The current overriding function is hidden by another - // overriding function; remove this one. - Pos = Overriding.erase(Pos); - PosEnd = Overriding.end(); - } else { - ++Pos; - } - } + for (const UniqueVirtualMethod &OP : Overriding) + if (&M != &OP && + OP.Method->getParent()->isVirtuallyDerivedFrom( + M.InVirtualSubobject)) + return true; + return false; + }; + + Overriding.erase( + std::remove_if(Overriding.begin(), Overriding.end(), IsHidden), + Overriding.end()); } } } diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp index 06a08bd..98b7e36 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp @@ -514,6 +514,12 @@ void Lexer::lexVerbatimBlockBody(Token &T) { if (CommentState == LCS_InsideCComment) skipLineStartingDecorations(); + if (BufferPtr == CommentEnd) { + formTokenWithChars(T, BufferPtr, tok::verbatim_block_line); + T.setVerbatimBlockText(""); + return; + } + lexVerbatimBlockFirstLine(T); } diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index dc08d23..8eff4c4 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -44,6 +44,12 @@ bool Decl::isOutOfLine() const { return !getLexicalDeclContext()->Equals(getDeclContext()); } +TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx) + : Decl(TranslationUnit, nullptr, SourceLocation()), + DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) { + Hidden = Ctx.getLangOpts().ModulesLocalVisibility; +} + //===----------------------------------------------------------------------===// // NamedDecl Implementation //===----------------------------------------------------------------------===// @@ -894,13 +900,13 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { // If the type of the function uses a type with unique-external // linkage, it's not legally usable from outside this translation unit. - // But only look at the type-as-written. If this function has an auto-deduced - // return type, we can't compute the linkage of that type because it could - // require looking at the linkage of this function, and we don't need this - // for correctness because the type is not part of the function's - // signature. - // FIXME: This is a hack. We should be able to solve this circularity and the - // one in getLVForNamespaceScopeDecl for Functions some other way. + // But only look at the type-as-written. If this function has an + // auto-deduced return type, we can't compute the linkage of that type + // because it could require looking at the linkage of this function, and we + // don't need this for correctness because the type is not part of the + // function's signature. + // FIXME: This is a hack. We should be able to solve this circularity and + // the one in getLVForNamespaceScopeDecl for Functions some other way. { QualType TypeAsWritten = MD->getType(); if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) @@ -1445,74 +1451,127 @@ void NamedDecl::getNameForDiagnostic(raw_ostream &OS, printName(OS); } -bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { - assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch"); +static bool isKindReplaceableBy(Decl::Kind OldK, Decl::Kind NewK) { + // For method declarations, we never replace. + if (ObjCMethodDecl::classofKind(NewK)) + return false; - // UsingDirectiveDecl's are not really NamedDecl's, and all have same name. - // We want to keep it, unless it nominates same namespace. - if (getKind() == Decl::UsingDirective) { - return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() - ->getOriginalNamespace() == - cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace() - ->getOriginalNamespace(); + if (OldK == NewK) + return true; + + // A compatibility alias for a class can be replaced by an interface. + if (ObjCCompatibleAliasDecl::classofKind(OldK) && + ObjCInterfaceDecl::classofKind(NewK)) + return true; + + // A typedef-declaration, alias-declaration, or Objective-C class declaration + // can replace another declaration of the same type. Semantic analysis checks + // that we have matching types. + if ((TypedefNameDecl::classofKind(OldK) || + ObjCInterfaceDecl::classofKind(OldK)) && + (TypedefNameDecl::classofKind(NewK) || + ObjCInterfaceDecl::classofKind(NewK))) + return true; + + // Otherwise, a kind mismatch implies that the declaration is not replaced. + return false; +} + +template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) { + return true; +} +static bool isRedeclarableImpl(...) { return false; } +static bool isRedeclarable(Decl::Kind K) { + switch (K) { +#define DECL(Type, Base) \ + case Decl::Type: \ + return isRedeclarableImpl((Type##Decl *)nullptr); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" } + llvm_unreachable("unknown decl kind"); +} - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) - // For function declarations, we keep track of redeclarations. - return FD->getPreviousDecl() == OldD; +bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { + assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch"); - // For function templates, the underlying function declarations are linked. - if (const FunctionTemplateDecl *FunctionTemplate - = dyn_cast<FunctionTemplateDecl>(this)) - if (const FunctionTemplateDecl *OldFunctionTemplate - = dyn_cast<FunctionTemplateDecl>(OldD)) - return FunctionTemplate->getTemplatedDecl() - ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl()); - - // For method declarations, we keep track of redeclarations. - if (isa<ObjCMethodDecl>(this)) + // Never replace one imported declaration with another; we need both results + // when re-exporting. + if (OldD->isFromASTFile() && isFromASTFile()) return false; - // FIXME: Is this correct if one of the decls comes from an inline namespace? - if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD)) - return true; + if (!isKindReplaceableBy(OldD->getKind(), getKind())) + return false; - if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD)) - return cast<UsingShadowDecl>(this)->getTargetDecl() == - cast<UsingShadowDecl>(OldD)->getTargetDecl(); + // Inline namespaces can give us two declarations with the same + // name and kind in the same scope but different contexts; we should + // keep both declarations in this case. + if (!this->getDeclContext()->getRedeclContext()->Equals( + OldD->getDeclContext()->getRedeclContext())) + return false; - if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD)) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) + // For function declarations, we keep track of redeclarations. + // FIXME: This returns false for functions that should in fact be replaced. + // Instead, perform some kind of type check? + if (FD->getPreviousDecl() != OldD) + return false; + + // For function templates, the underlying function declarations are linked. + if (const FunctionTemplateDecl *FunctionTemplate = + dyn_cast<FunctionTemplateDecl>(this)) + return FunctionTemplate->getTemplatedDecl()->declarationReplaces( + cast<FunctionTemplateDecl>(OldD)->getTemplatedDecl()); + + // Using shadow declarations can be overloaded on their target declarations + // if they introduce functions. + // FIXME: If our target replaces the old target, can we replace the old + // shadow declaration? + if (auto *USD = dyn_cast<UsingShadowDecl>(this)) + if (USD->getTargetDecl() != cast<UsingShadowDecl>(OldD)->getTargetDecl()) + return false; + + // Using declarations can be overloaded if they introduce functions. + if (auto *UD = dyn_cast<UsingDecl>(this)) { ASTContext &Context = getASTContext(); - return Context.getCanonicalNestedNameSpecifier( - cast<UsingDecl>(this)->getQualifier()) == + return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) == Context.getCanonicalNestedNameSpecifier( - cast<UsingDecl>(OldD)->getQualifier()); + cast<UsingDecl>(OldD)->getQualifier()); } - - if (isa<UnresolvedUsingValueDecl>(this) && - isa<UnresolvedUsingValueDecl>(OldD)) { + if (auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) { ASTContext &Context = getASTContext(); - return Context.getCanonicalNestedNameSpecifier( - cast<UnresolvedUsingValueDecl>(this)->getQualifier()) == + return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) == Context.getCanonicalNestedNameSpecifier( cast<UnresolvedUsingValueDecl>(OldD)->getQualifier()); } - // A typedef of an Objective-C class type can replace an Objective-C class - // declaration or definition, and vice versa. - // FIXME: Is this correct if one of the decls comes from an inline namespace? - if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) || - (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD))) - return true; + // UsingDirectiveDecl's are not really NamedDecl's, and all have same name. + // We want to keep it, unless it nominates same namespace. + if (auto *UD = dyn_cast<UsingDirectiveDecl>(this)) + return UD->getNominatedNamespace()->getOriginalNamespace() == + cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace() + ->getOriginalNamespace(); + + if (!IsKnownNewer && isRedeclarable(getKind())) { + // Check whether this is actually newer than OldD. We want to keep the + // newer declaration. This loop will usually only iterate once, because + // OldD is usually the previous declaration. + for (auto D : redecls()) { + if (D == OldD) + break; - // For non-function declarations, if the declarations are of the - // same kind and have the same parent then this must be a redeclaration, - // or semantic analysis would not have given us the new declaration. - // Note that inline namespaces can give us two declarations with the same - // name and kind in the same scope but different contexts. - return this->getKind() == OldD->getKind() && - this->getDeclContext()->getRedeclContext()->Equals( - OldD->getDeclContext()->getRedeclContext()); + // If we reach the canonical declaration, then OldD is not actually older + // than this one. + // + // FIXME: In this case, we should not add this decl to the lookup table. + if (D->isCanonicalDecl()) + return false; + } + } + + // It's a newer declaration of the same kind of declaration in the same scope, + // and not an overload: we want this decl instead of the existing one. + return true; } bool NamedDecl::hasLinkage() const { @@ -1684,8 +1743,7 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, if (NumTPLists > 0) { TemplParamLists = new (Context) TemplateParameterList*[NumTPLists]; NumTemplParamLists = NumTPLists; - for (unsigned i = NumTPLists; i-- > 0; ) - TemplParamLists[i] = TPLists[i]; + std::copy(TPLists, TPLists + NumTPLists, TemplParamLists); } } @@ -1717,6 +1775,8 @@ VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, "VarDeclBitfields too large!"); static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned), "ParmVarDeclBitfields too large!"); + static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned), + "NonParmVarDeclBitfields too large!"); AllBits = 0; VarDeclBits.SClass = SC; // Everything else is implicitly initialized to false. @@ -1743,9 +1803,12 @@ void VarDecl::setStorageClass(StorageClass SC) { VarDecl::TLSKind VarDecl::getTLSKind() const { switch (VarDeclBits.TSCSpec) { case TSCS_unspecified: - if (hasAttr<ThreadAttr>()) - return TLS_Static; - return TLS_None; + if (!hasAttr<ThreadAttr>()) + return TLS_None; + return getASTContext().getLangOpts().isCompatibleWithMSVC( + LangOptions::MSVC2015) + ? TLS_Dynamic + : TLS_Static; case TSCS___thread: // Fall through. case TSCS__Thread_local: return TLS_Static; @@ -1825,9 +1888,8 @@ bool VarDecl::isInExternCXXContext() const { VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); } -VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( - ASTContext &C) const -{ +VarDecl::DefinitionKind +VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // C++ [basic.def]p2: // A declaration is a definition unless [...] it contains the 'extern' // specifier or a linkage-specification and neither an initializer [...], @@ -1867,6 +1929,10 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( if (hasAttr<AliasAttr>()) return Definition; + if (const auto *SAA = getAttr<SelectAnyAttr>()) + if (!SAA->isInherited()) + return Definition; + // A variable template specialization (other than a static data member // template or an explicit specialization) is a declaration until we // instantiate its initializer. @@ -2460,39 +2526,6 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace(); } -FunctionDecl * -FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const { - ASTContext &Ctx = getASTContext(); - if (!Ctx.getLangOpts().SizedDeallocation) - return nullptr; - - if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) - return nullptr; - if (getDeclName().getCXXOverloadedOperator() != OO_Delete && - getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) - return nullptr; - if (isa<CXXRecordDecl>(getDeclContext())) - return nullptr; - - if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) - return nullptr; - - if (getNumParams() != 2 || isVariadic() || - !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getParamType(1), - Ctx.getSizeType())) - return nullptr; - - // This is a sized deallocation function. Find the corresponding unsized - // deallocation function. - lookup_const_result R = getDeclContext()->lookup(getDeclName()); - for (lookup_const_result::iterator RI = R.begin(), RE = R.end(); RI != RE; - ++RI) - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI)) - if (FD->getNumParams() == 1 && !FD->isVariadic()) - return FD; - return nullptr; -} - LanguageLinkage FunctionDecl::getLanguageLinkage() const { return getDeclLanguageLinkage(*this); } @@ -2550,10 +2583,6 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { IsInline = true; } -const FunctionDecl *FunctionDecl::getCanonicalDecl() const { - return getFirstDecl(); -} - FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } /// \brief Returns a value indicating whether this function @@ -2581,7 +2610,14 @@ unsigned FunctionDecl::getBuiltinID() const { // extern "C". // FIXME: A recognised library function may not be directly in an extern "C" // declaration, for instance "extern "C" { namespace std { decl } }". - if (!LinkageDecl || LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c) + if (!LinkageDecl) { + if (BuiltinID == Builtin::BI__GetExceptionInfo && + Context.getTargetInfo().getCXXABI().isMicrosoft() && + isInStdNamespace()) + return Builtin::BI__GetExceptionInfo; + return 0; + } + if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c) return 0; } @@ -2796,6 +2832,18 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const { return RTRange; } +bool FunctionDecl::hasUnusedResultAttr() const { + QualType RetType = getReturnType(); + if (RetType->isRecordType()) { + const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl(); + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this); + if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() && + !(MD && MD->getCorrespondingMethodInClass(Ret, true))) + return true; + } + return hasAttr<WarnUnusedResultAttr>(); +} + /// \brief For an inline function definition in C, or for a gnu_inline function /// in C++, determine whether the definition will be externally visible. /// @@ -3077,6 +3125,8 @@ DependentFunctionTemplateSpecializationInfo:: DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts, const TemplateArgumentListInfo &TArgs) : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) { + static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0, + "Trailing data is unaligned!"); d.NumTemplates = Ts.size(); d.NumArgs = TArgs.size(); @@ -3590,7 +3640,7 @@ void RecordDecl::completeDefinition() { /// This which can be turned on with an attribute, pragma, or the /// -mms-bitfields command-line option. bool RecordDecl::isMsStruct(const ASTContext &C) const { - return hasAttr<MsStructAttr>() || C.getLangOpts().MSBitfields == 1; + return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1; } static bool isFieldOrIndirectField(Decl::Kind K) { @@ -3747,6 +3797,13 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C); } +void ExternCContextDecl::anchor() { } + +ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C, + TranslationUnitDecl *DC) { + return new (C, DC) ExternCContextDecl(DC); +} + void LabelDecl::anchor() { } LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, @@ -3885,6 +3942,21 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, void TypedefNameDecl::anchor() { } +TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const { + if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) { + auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl(); + auto *ThisTypedef = this; + if (AnyRedecl && OwningTypedef) { + OwningTypedef = OwningTypedef->getCanonicalDecl(); + ThisTypedef = ThisTypedef->getCanonicalDecl(); + } + if (OwningTypedef == ThisTypedef) + return TT->getDecl(); + } + + return nullptr; +} + TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index a46787f..70bd16f 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -66,6 +66,12 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context, void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, DeclContext *Parent, std::size_t Extra) { assert(!Parent || &Parent->getParentASTContext() == &Ctx); + // With local visibility enabled, we track the owning module even for local + // declarations. + if (Ctx.getLangOpts().ModulesLocalVisibility) { + void *Buffer = ::operator new(sizeof(Module *) + Size + Extra, Ctx); + return new (Buffer) Module*(nullptr) + 1; + } return ::operator new(Size + Extra, Ctx); } @@ -74,6 +80,10 @@ Module *Decl::getOwningModuleSlow() const { return getASTContext().getExternalSource()->getModule(getOwningModuleID()); } +bool Decl::hasLocalOwningModuleStorage() const { + return getASTContext().getLangOpts().ModulesLocalVisibility; +} + const char *Decl::getDeclKindName() const { switch (DeclKind) { default: llvm_unreachable("Declaration not in DeclNodes.inc!"); @@ -336,20 +346,34 @@ bool Decl::isReferenced() const { static AvailabilityResult CheckAvailability(ASTContext &Context, const AvailabilityAttr *A, std::string *Message) { - StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); - StringRef PrettyPlatformName - = AvailabilityAttr::getPrettyPlatformName(TargetPlatform); - if (PrettyPlatformName.empty()) - PrettyPlatformName = TargetPlatform; + VersionTuple TargetMinVersion = + Context.getTargetInfo().getPlatformMinVersion(); - VersionTuple TargetMinVersion = Context.getTargetInfo().getPlatformMinVersion(); if (TargetMinVersion.empty()) return AR_Available; + // Check if this is an App Extension "platform", and if so chop off + // the suffix for matching with the actual platform. + StringRef ActualPlatform = A->getPlatform()->getName(); + StringRef RealizedPlatform = ActualPlatform; + if (Context.getLangOpts().AppExt) { + size_t suffix = RealizedPlatform.rfind("_app_extension"); + if (suffix != StringRef::npos) + RealizedPlatform = RealizedPlatform.slice(0, suffix); + } + + StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); + // Match the platform name. - if (A->getPlatform()->getName() != TargetPlatform) + if (RealizedPlatform != TargetPlatform) return AR_Available; - + + StringRef PrettyPlatformName + = AvailabilityAttr::getPrettyPlatformName(ActualPlatform); + + if (PrettyPlatformName.empty()) + PrettyPlatformName = ActualPlatform; + std::string HintMessage; if (!A->getMessage().empty()) { HintMessage = " - "; @@ -583,6 +607,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Block: case Captured: case TranslationUnit: + case ExternCContext: case UsingDirective: case ClassTemplateSpecialization: @@ -846,6 +871,10 @@ bool DeclContext::isDependentContext() const { return getLexicalParent()->isDependentContext(); } + // FIXME: A variable template is a dependent context, but is not a + // DeclContext. A context within it (such as a lambda-expression) + // should be considered dependent. + return getParent() && getParent()->isDependentContext(); } @@ -889,6 +918,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const { DeclContext *DeclContext::getPrimaryContext() { switch (DeclKind) { case Decl::TranslationUnit: + case Decl::ExternCContext: case Decl::LinkageSpec: case Decl::Block: case Decl::Captured: @@ -991,23 +1021,24 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls, /// built a lookup map. For every name in the map, pull in the new names from /// the external storage. void DeclContext::reconcileExternalVisibleStorage() const { - assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer()); + assert(NeedToReconcileExternalVisibleStorage && LookupPtr); NeedToReconcileExternalVisibleStorage = false; - for (auto &Lookup : *LookupPtr.getPointer()) + for (auto &Lookup : *LookupPtr) Lookup.second.setHasExternalDecls(); } /// \brief Load the declarations within this lexical storage from an /// external source. -void +/// \return \c true if any declarations were added. +bool DeclContext::LoadLexicalDeclsFromExternalStorage() const { ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); // Notify that we have a DeclContext that is initializing. ExternalASTSource::Deserializing ADeclContext(Source); - + // Load the external declarations, if any. SmallVector<Decl*, 64> Decls; ExternalLexicalStorage = false; @@ -1017,11 +1048,11 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { case ELR_Failure: case ELR_AlreadyLoaded: - return; + return false; } if (Decls.empty()) - return; + return false; // We may have already loaded just the fields of this record, in which case // we need to ignore them. @@ -1038,6 +1069,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { FirstDecl = ExternalFirst; if (!LastDecl) LastDecl = ExternalLast; + return true; } DeclContext::lookup_result @@ -1045,7 +1077,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name) { ASTContext &Context = DC->getParentASTContext(); StoredDeclsMap *Map; - if (!(Map = DC->LookupPtr.getPointer())) + if (!(Map = DC->LookupPtr)) Map = DC->CreateStoredDeclsMap(Context); if (DC->NeedToReconcileExternalVisibleStorage) DC->reconcileExternalVisibleStorage(); @@ -1061,7 +1093,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, ArrayRef<NamedDecl*> Decls) { ASTContext &Context = DC->getParentASTContext(); StoredDeclsMap *Map; - if (!(Map = DC->LookupPtr.getPointer())) + if (!(Map = DC->LookupPtr)) Map = DC->CreateStoredDeclsMap(Context); if (DC->NeedToReconcileExternalVisibleStorage) DC->reconcileExternalVisibleStorage(); @@ -1078,7 +1110,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, // first. llvm::SmallVector<unsigned, 8> Skip; for (unsigned I = 0, N = Decls.size(); I != N; ++I) - if (List.HandleRedeclaration(Decls[I])) + if (List.HandleRedeclaration(Decls[I], /*IsKnownNewer*/false)) Skip.push_back(I); Skip.push_back(Decls.size()); @@ -1155,7 +1187,7 @@ void DeclContext::removeDecl(Decl *D) { // Remove only decls that have a name if (!ND->getDeclName()) return; - StoredDeclsMap *Map = getPrimaryContext()->LookupPtr.getPointer(); + StoredDeclsMap *Map = getPrimaryContext()->LookupPtr; if (!Map) return; StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName()); @@ -1243,32 +1275,38 @@ static bool shouldBeHidden(NamedDecl *D) { StoredDeclsMap *DeclContext::buildLookup() { assert(this == getPrimaryContext() && "buildLookup called on non-primary DC"); - // FIXME: Should we keep going if hasExternalVisibleStorage? - if (!LookupPtr.getInt()) - return LookupPtr.getPointer(); + if (!HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) + return LookupPtr; SmallVector<DeclContext *, 2> Contexts; collectAllContexts(Contexts); - for (unsigned I = 0, N = Contexts.size(); I != N; ++I) - buildLookupImpl<&DeclContext::decls_begin, - &DeclContext::decls_end>(Contexts[I]); + + if (HasLazyExternalLexicalLookups) { + HasLazyExternalLexicalLookups = false; + for (auto *DC : Contexts) { + if (DC->hasExternalLexicalStorage()) + HasLazyLocalLexicalLookups |= + DC->LoadLexicalDeclsFromExternalStorage(); + } + + if (!HasLazyLocalLexicalLookups) + return LookupPtr; + } + + for (auto *DC : Contexts) + buildLookupImpl(DC, hasExternalVisibleStorage()); // We no longer have any lazy decls. - LookupPtr.setInt(false); - return LookupPtr.getPointer(); + HasLazyLocalLexicalLookups = false; + return LookupPtr; } /// buildLookupImpl - Build part of the lookup data structure for the /// declarations contained within DCtx, which will either be this /// DeclContext, a DeclContext linked to it, or a transparent context /// nested within it. -template<DeclContext::decl_iterator (DeclContext::*Begin)() const, - DeclContext::decl_iterator (DeclContext::*End)() const> -void DeclContext::buildLookupImpl(DeclContext *DCtx) { - for (decl_iterator I = (DCtx->*Begin)(), E = (DCtx->*End)(); - I != E; ++I) { - Decl *D = *I; - +void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) { + for (Decl *D : DCtx->noload_decls()) { // Insert this declaration into the lookup structure, but only if // it's semantically within its decl context. Any other decls which // should be found in this context are added eagerly. @@ -1282,39 +1320,46 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx) { (!ND->isFromASTFile() || (isTranslationUnit() && !getParentASTContext().getLangOpts().CPlusPlus))) - makeDeclVisibleInContextImpl(ND, false); + makeDeclVisibleInContextImpl(ND, Internal); // If this declaration is itself a transparent declaration context // or inline namespace, add the members of this declaration of that // context (recursively). if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D)) if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) - buildLookupImpl<Begin, End>(InnerCtx); + buildLookupImpl(InnerCtx, Internal); } } +NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr; + DeclContext::lookup_result -DeclContext::lookup(DeclarationName Name) { +DeclContext::lookup(DeclarationName Name) const { assert(DeclKind != Decl::LinkageSpec && "Should not perform lookups into linkage specs!"); - DeclContext *PrimaryContext = getPrimaryContext(); + const DeclContext *PrimaryContext = getPrimaryContext(); 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 we have an external source, ensure that any later redeclarations of this + // context have been loaded, since they may add names to the result of this + // lookup (or add external visible storage). + ExternalASTSource *Source = getParentASTContext().getExternalSource(); + if (Source) + (void)cast<Decl>(this)->getMostRecentDecl(); if (hasExternalVisibleStorage()) { + assert(Source && "external visible storage but no external source?"); + if (NeedToReconcileExternalVisibleStorage) reconcileExternalVisibleStorage(); - StoredDeclsMap *Map = LookupPtr.getPointer(); + StoredDeclsMap *Map = LookupPtr; - if (LookupPtr.getInt()) - Map = buildLookup(); + if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups) + // FIXME: Make buildLookup const? + Map = const_cast<DeclContext*>(this)->buildLookup(); if (!Map) Map = CreateStoredDeclsMap(getParentASTContext()); @@ -1325,28 +1370,27 @@ DeclContext::lookup(DeclarationName Name) { if (!R.second && !R.first->second.hasExternalDecls()) return R.first->second.getLookupResult(); - ExternalASTSource *Source = getParentASTContext().getExternalSource(); if (Source->FindExternalVisibleDeclsByName(this, Name) || !R.second) { - if (StoredDeclsMap *Map = LookupPtr.getPointer()) { + if (StoredDeclsMap *Map = LookupPtr) { StoredDeclsMap::iterator I = Map->find(Name); if (I != Map->end()) return I->second.getLookupResult(); } } - return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); + return lookup_result(); } - StoredDeclsMap *Map = LookupPtr.getPointer(); - if (LookupPtr.getInt()) - Map = buildLookup(); + StoredDeclsMap *Map = LookupPtr; + if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups) + Map = const_cast<DeclContext*>(this)->buildLookup(); if (!Map) - return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); + return lookup_result(); StoredDeclsMap::iterator I = Map->find(Name); if (I == Map->end()) - return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); + return lookup_result(); return I->second.getLookupResult(); } @@ -1355,40 +1399,29 @@ DeclContext::lookup_result DeclContext::noload_lookup(DeclarationName Name) { assert(DeclKind != Decl::LinkageSpec && "Should not perform lookups into linkage specs!"); - if (!hasExternalVisibleStorage()) - return lookup(Name); DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) return PrimaryContext->noload_lookup(Name); - StoredDeclsMap *Map = LookupPtr.getPointer(); - if (LookupPtr.getInt()) { - // Carefully build the lookup map, without deserializing anything. + // If we have any lazy lexical declarations not in our lookup map, add them + // now. Don't import any external declarations, not even if we know we have + // some missing from the external visible lookups. + if (HasLazyLocalLexicalLookups) { SmallVector<DeclContext *, 2> Contexts; collectAllContexts(Contexts); for (unsigned I = 0, N = Contexts.size(); I != N; ++I) - buildLookupImpl<&DeclContext::noload_decls_begin, - &DeclContext::noload_decls_end>(Contexts[I]); - - // We no longer have any lazy decls. - LookupPtr.setInt(false); - - // There may now be names for which we have local decls but are - // missing the external decls. FIXME: Just set the hasExternalDecls - // flag on those names that have external decls. - NeedToReconcileExternalVisibleStorage = true; - - Map = LookupPtr.getPointer(); + buildLookupImpl(Contexts[I], hasExternalVisibleStorage()); + HasLazyLocalLexicalLookups = false; } + StoredDeclsMap *Map = LookupPtr; if (!Map) - return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); + return lookup_result(); StoredDeclsMap::iterator I = Map->find(Name); return I != Map->end() ? I->second.getLookupResult() - : lookup_result(lookup_iterator(nullptr), - lookup_iterator(nullptr)); + : lookup_result(); } void DeclContext::localUncachedLookup(DeclarationName Name, @@ -1404,8 +1437,9 @@ void DeclContext::localUncachedLookup(DeclarationName Name, } // If we have a lookup table, check there first. Maybe we'll get lucky. - if (Name && !LookupPtr.getInt()) { - if (StoredDeclsMap *Map = LookupPtr.getPointer()) { + // FIXME: Should we be checking these flags on the primary context? + if (Name && !HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) { + if (StoredDeclsMap *Map = LookupPtr) { StoredDeclsMap::iterator Pos = Map->find(Name); if (Pos != Map->end()) { Results.insert(Results.end(), @@ -1418,6 +1452,8 @@ void DeclContext::localUncachedLookup(DeclarationName Name, // Slow case: grovel through the declarations in our chain looking for // matches. + // FIXME: If we have lazy external declarations, this will not find them! + // FIXME: Should we CollectAllContexts and walk them all here? for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) { if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) if (ND->getDeclName() == Name) @@ -1498,7 +1534,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, // FIXME: As a performance hack, don't add such decls into the translation // unit unless we're in C++, since qualified lookup into the TU is never // performed. - if (LookupPtr.getPointer() || hasExternalVisibleStorage() || + if (LookupPtr || hasExternalVisibleStorage() || ((!Recoverable || D->getDeclContext() != D->getLexicalDeclContext()) && (getParentASTContext().getLangOpts().CPlusPlus || !isTranslationUnit()))) { @@ -1508,7 +1544,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, buildLookup(); makeDeclVisibleInContextImpl(D, Internal); } else { - LookupPtr.setInt(true); + HasLazyLocalLexicalLookups = true; } // If we are a transparent context or inline namespace, insert into our @@ -1526,7 +1562,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) { // Find or create the stored declaration map. - StoredDeclsMap *Map = LookupPtr.getPointer(); + StoredDeclsMap *Map = LookupPtr; if (!Map) { ASTContext *C = &getParentASTContext(); Map = CreateStoredDeclsMap(*C); @@ -1555,12 +1591,12 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) { return; } - else if (DeclNameEntries.isNull()) { + if (DeclNameEntries.isNull()) { DeclNameEntries.setOnlyValue(D); return; } - if (DeclNameEntries.HandleRedeclaration(D)) { + if (DeclNameEntries.HandleRedeclaration(D, /*IsKnownNewer*/!Internal)) { // This declaration has replaced an existing one for which // declarationReplaces returns true. return; @@ -1570,15 +1606,17 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) { DeclNameEntries.AddSubsequentDecl(D); } +UsingDirectiveDecl *DeclContext::udir_iterator::operator*() const { + return cast<UsingDirectiveDecl>(*I); +} + /// Returns iterator range [First, Last) of UsingDirectiveDecls stored within /// this context. DeclContext::udir_range DeclContext::using_directives() const { // FIXME: Use something more efficient than normal lookup for using // directives. In C++, using directives are looked up more than anything else. - lookup_const_result Result = lookup(UsingDirectiveDecl::getName()); - return udir_range( - reinterpret_cast<UsingDirectiveDecl *const *>(Result.begin()), - reinterpret_cast<UsingDirectiveDecl *const *>(Result.end())); + lookup_result Result = lookup(UsingDirectiveDecl::getName()); + return udir_range(Result.begin(), Result.end()); } //===----------------------------------------------------------------------===// @@ -1586,7 +1624,7 @@ DeclContext::udir_range DeclContext::using_directives() const { //===----------------------------------------------------------------------===// StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const { - assert(!LookupPtr.getPointer() && "context already has a decls map"); + assert(!LookupPtr && "context already has a decls map"); assert(getPrimaryContext() == this && "creating decls map on non-primary context"); @@ -1598,7 +1636,7 @@ StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const { M = new StoredDeclsMap(); M->Previous = C.LastSDM; C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent); - LookupPtr.setPointer(M); + LookupPtr = M; return M; } @@ -1630,11 +1668,11 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C, assert(Parent->isDependentContext() && "cannot iterate dependent diagnostics of non-dependent context"); Parent = Parent->getPrimaryContext(); - if (!Parent->LookupPtr.getPointer()) + if (!Parent->LookupPtr) Parent->CreateStoredDeclsMap(C); - DependentStoredDeclsMap *Map - = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr.getPointer()); + DependentStoredDeclsMap *Map = + static_cast<DependentStoredDeclsMap *>(Parent->LookupPtr); // Allocate the copy of the PartialDiagnostic via the ASTContext's // BumpPtrAllocator, rather than the ASTContext itself. diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index 9af8c4b..b00b8a0 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -991,7 +991,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { if (!isLambda()) return nullptr; DeclarationName Name = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); - DeclContext::lookup_const_result Calls = lookup(Name); + DeclContext::lookup_result Calls = lookup(Name); assert(!Calls.empty() && "Missing lambda call operator!"); assert(Calls.size() == 1 && "More than one lambda call operator!"); @@ -1008,7 +1008,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const { if (!isLambda()) return nullptr; DeclarationName Name = &getASTContext().Idents.get(getLambdaStaticInvokerName()); - DeclContext::lookup_const_result Invoker = lookup(Name); + DeclContext::lookup_result Invoker = lookup(Name); if (Invoker.empty()) return nullptr; assert(Invoker.size() == 1 && "More than one static invoker operator!"); NamedDecl *InvokerFun = Invoker.front(); @@ -1173,7 +1173,7 @@ static void CollectVisibleConversions(ASTContext &Context, /// getVisibleConversionFunctions - get all conversion functions visible /// in current class; including conversion function templates. -std::pair<CXXRecordDecl::conversion_iterator,CXXRecordDecl::conversion_iterator> +llvm::iterator_range<CXXRecordDecl::conversion_iterator> CXXRecordDecl::getVisibleConversionFunctions() { ASTContext &Ctx = getASTContext(); @@ -1189,7 +1189,7 @@ CXXRecordDecl::getVisibleConversionFunctions() { data().ComputedVisibleConversions = true; } } - return std::make_pair(Set->begin(), Set->end()); + return llvm::make_range(Set->begin(), Set->end()); } void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { @@ -1307,7 +1307,7 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { = Context.DeclarationNames.getCXXDestructorName( Context.getCanonicalType(ClassType)); - DeclContext::lookup_const_result R = lookup(Name); + DeclContext::lookup_result R = lookup(Name); if (R.empty()) return nullptr; @@ -1315,6 +1315,28 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { return Dtor; } +bool CXXRecordDecl::isAnyDestructorNoReturn() const { + // Destructor is noreturn. + if (const CXXDestructorDecl *Destructor = getDestructor()) + if (Destructor->isNoReturn()) + return true; + + // Check base classes destructor for noreturn. + for (const auto &Base : bases()) + if (Base.getType()->getAsCXXRecordDecl()->isAnyDestructorNoReturn()) + return true; + + // Check fields for noreturn. + for (const auto *Field : fields()) + if (const CXXRecordDecl *RD = + Field->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) + if (RD->isAnyDestructorNoReturn()) + return true; + + // All destructors are not noreturn. + return false; +} + void CXXRecordDecl::completeDefinition() { completeDefinition(nullptr); } @@ -1418,9 +1440,8 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, return nullptr; } - lookup_const_result Candidates = RD->lookup(getDeclName()); - for (NamedDecl * const * I = Candidates.begin(); I != Candidates.end(); ++I) { - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*I); + for (auto *ND : RD->lookup(getDeclName())) { + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND); if (!MD) continue; if (recursivelyOverrides(MD, this)) @@ -1491,8 +1512,8 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const { // This function is a usual deallocation function if there are no // single-parameter deallocation functions of the same kind. - DeclContext::lookup_const_result R = getDeclContext()->lookup(getDeclName()); - for (DeclContext::lookup_const_result::iterator I = R.begin(), E = R.end(); + DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName()); + for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end(); I != E; ++I) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) if (FD->getNumParams() == 1) @@ -1740,6 +1761,10 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isImplicitlyDeclared, isConstexpr); } +CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const { + return CtorInitializers.get(getASTContext().getExternalSource()); +} + CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const { assert(isDelegatingConstructor() && "Not a delegating constructor!"); Expr *E = (*init_begin())->getInit()->IgnoreImplicit(); @@ -1887,6 +1912,15 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isInline, isImplicitlyDeclared); } +void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD) { + auto *First = cast<CXXDestructorDecl>(getFirstDecl()); + if (OD && !First->OperatorDelete) { + First->OperatorDelete = OD; + if (auto *L = getASTMutationListener()) + L->ResolvedOperatorDelete(First, OD); + } +} + void CXXConversionDecl::anchor() { } CXXConversionDecl * diff --git a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp index 9861f22..512837f 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp @@ -18,6 +18,8 @@ using namespace clang; DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { + static_assert(sizeof(DeclGroup) % llvm::AlignOf<void *>::Alignment == 0, + "Trailing data is unaligned!"); assert(NumDecls > 1 && "Invalid DeclGroup"); unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls; void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment); diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index ed53675..a63ba7e 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -54,8 +54,8 @@ void ObjCContainerDecl::anchor() { } /// ObjCIvarDecl * ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const { - lookup_const_result R = lookup(Id); - for (lookup_const_iterator Ivar = R.begin(), IvarEnd = R.end(); + lookup_result R = lookup(Id); + for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end(); Ivar != IvarEnd; ++Ivar) { if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar)) return ivar; @@ -83,8 +83,8 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, // + (float) class_method; // @end // - lookup_const_result R = lookup(Sel); - for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end(); + lookup_result R = lookup(Sel); + for (lookup_iterator Meth = R.begin(), MethEnd = R.end(); Meth != MethEnd; ++Meth) { ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); if (MD && MD->isInstanceMethod() == isInstance) @@ -101,8 +101,8 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, 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(); + lookup_result R = lookup(Sel); + for (lookup_iterator Meth = R.begin(), MethEnd = R.end(); Meth != MethEnd; ++Meth) { ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); if (MD && MD->isInstanceMethod() && !MD->isImplicit()) @@ -161,8 +161,8 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, return nullptr; } - DeclContext::lookup_const_result R = DC->lookup(propertyID); - for (DeclContext::lookup_const_iterator I = R.begin(), E = R.end(); I != E; + DeclContext::lookup_result R = DC->lookup(propertyID); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) return PD; @@ -334,9 +334,8 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( return; // Merge ProtocolRefs into class's protocol list; - for (auto *P : all_referenced_protocols()) { - ProtocolRefs.push_back(P); - } + ProtocolRefs.append(all_referenced_protocol_begin(), + all_referenced_protocol_end()); data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C); } @@ -617,8 +616,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( // Look through local category implementations associated with the class. if (!Method) - Method = Instance ? getCategoryInstanceMethod(Sel) - : getCategoryClassMethod(Sel); + Method = getCategoryMethod(Sel, Instance); // Before we give up, check if the selector is an instance method. // But only in the root. This matches gcc's behavior and what the @@ -1101,7 +1099,7 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { if (NumArgs > 1) return nullptr; - if (!isInstanceMethod() || getMethodFamily() != OMF_None) + if (!isInstanceMethod()) return nullptr; if (isPropertyAccessor()) { @@ -1822,6 +1820,11 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, } } +ObjCImplementationDecl::init_const_iterator +ObjCImplementationDecl::init_begin() const { + return IvarInitializers.get(getASTContext().getExternalSource()); +} + raw_ostream &clang::operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID) { OS << ID.getName(); diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index c0f3e17..d8cd40e 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -733,8 +733,10 @@ void DeclPrinter::VisitImportDecl(ImportDecl *D) { void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { Out << "static_assert("; D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation); - Out << ", "; - D->getMessage()->printPretty(Out, nullptr, Policy, Indentation); + if (StringLiteral *SL = D->getMessage()) { + Out << ", "; + SL->printPretty(Out, nullptr, Policy, Indentation); + } Out << ")"; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index 0d1d2a4..6374a92 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -160,17 +160,43 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c return Common; } -template <class EntryType> -typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType* +template<class EntryType> +typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * RedeclarableTemplateDecl::findSpecializationImpl( - llvm::FoldingSetVector<EntryType> &Specs, - ArrayRef<TemplateArgument> Args, - void *&InsertPos) { + llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args, + void *&InsertPos) { typedef SpecEntryTraits<EntryType> SETraits; llvm::FoldingSetNodeID ID; EntryType::Profile(ID,Args, getASTContext()); EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos); - return Entry ? SETraits::getMostRecentDecl(Entry) : nullptr; + return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr; +} + +template<class Derived, class EntryType> +void RedeclarableTemplateDecl::addSpecializationImpl( + llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry, + void *InsertPos) { + typedef SpecEntryTraits<EntryType> SETraits; + if (InsertPos) { +#ifndef NDEBUG + void *CorrectInsertPos; + assert(!findSpecializationImpl(Specializations, + SETraits::getTemplateArgs(Entry), + CorrectInsertPos) && + InsertPos == CorrectInsertPos && + "given incorrect InsertPos for specialization"); +#endif + Specializations.InsertNode(Entry, InsertPos); + } else { + EntryType *Existing = Specializations.GetOrInsertNode(Entry); + (void)Existing; + assert(SETraits::getDecl(Existing)->isCanonicalDecl() && + "non-canonical specialization?"); + } + + if (ASTMutationListener *L = getASTMutationListener()) + L->AddedCXXTemplateSpecialization(cast<Derived>(this), + SETraits::getDecl(Entry)); } /// \brief Generate the injected template arguments for the given template @@ -246,7 +272,11 @@ FunctionTemplateDecl::newCommon(ASTContext &C) const { } void FunctionTemplateDecl::LoadLazySpecializations() const { - Common *CommonPtr = getCommonPtr(); + // Grab the most recent declaration to ensure we've loaded any lazy + // redeclarations of this template. + // + // FIXME: Avoid walking the entire redeclaration chain here. + Common *CommonPtr = getMostRecentDecl()->getCommonPtr(); if (CommonPtr->LazySpecializations) { ASTContext &Context = getASTContext(); uint32_t *Specs = CommonPtr->LazySpecializations; @@ -270,12 +300,8 @@ FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void FunctionTemplateDecl::addSpecialization( FunctionTemplateSpecializationInfo *Info, void *InsertPos) { - if (InsertPos) - getSpecializations().InsertNode(Info, InsertPos); - else - getSpecializations().GetOrInsertNode(Info); - if (ASTMutationListener *L = getASTMutationListener()) - L->AddedCXXTemplateSpecialization(this, Info->Function); + addSpecializationImpl<FunctionTemplateDecl>(getSpecializations(), Info, + InsertPos); } ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() { @@ -320,7 +346,11 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, } void ClassTemplateDecl::LoadLazySpecializations() const { - Common *CommonPtr = getCommonPtr(); + // Grab the most recent declaration to ensure we've loaded any lazy + // redeclarations of this template. + // + // FIXME: Avoid walking the entire redeclaration chain here. + Common *CommonPtr = getMostRecentDecl()->getCommonPtr(); if (CommonPtr->LazySpecializations) { ASTContext &Context = getASTContext(); uint32_t *Specs = CommonPtr->LazySpecializations; @@ -357,16 +387,7 @@ ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) { - if (InsertPos) - getSpecializations().InsertNode(D, InsertPos); - else { - ClassTemplateSpecializationDecl *Existing - = getSpecializations().GetOrInsertNode(D); - (void)Existing; - assert(Existing->isCanonicalDecl() && "Non-canonical specialization?"); - } - if (ASTMutationListener *L = getASTMutationListener()) - L->AddedCXXTemplateSpecialization(this, D); + addSpecializationImpl<ClassTemplateDecl>(getSpecializations(), D, InsertPos); } ClassTemplatePartialSpecializationDecl * @@ -953,7 +974,11 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C, // TODO: Unify across class, function and variable templates? // May require moving this and Common to RedeclarableTemplateDecl. void VarTemplateDecl::LoadLazySpecializations() const { - Common *CommonPtr = getCommonPtr(); + // Grab the most recent declaration to ensure we've loaded any lazy + // redeclarations of this template. + // + // FIXME: Avoid walking the entire redeclaration chain here. + Common *CommonPtr = getMostRecentDecl()->getCommonPtr(); if (CommonPtr->LazySpecializations) { ASTContext &Context = getASTContext(); uint32_t *Specs = CommonPtr->LazySpecializations; @@ -990,16 +1015,7 @@ VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos) { - if (InsertPos) - getSpecializations().InsertNode(D, InsertPos); - else { - VarTemplateSpecializationDecl *Existing = - getSpecializations().GetOrInsertNode(D); - (void)Existing; - assert(Existing->isCanonicalDecl() && "Non-canonical specialization?"); - } - if (ASTMutationListener *L = getASTMutationListener()) - L->AddedCXXTemplateSpecialization(this, D); + addSpecializationImpl<VarTemplateDecl>(getSpecializations(), D, InsertPos); } VarTemplatePartialSpecializationDecl * diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 712de50..76a4da2 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -1141,40 +1141,13 @@ CallExpr::CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, RParenLoc = rparenloc; } -CallExpr::CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, +CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t, ExprValueKind VK, SourceLocation rparenloc) - : Expr(CallExprClass, t, VK, OK_Ordinary, - fn->isTypeDependent(), - fn->isValueDependent(), - fn->isInstantiationDependent(), - fn->containsUnexpandedParameterPack()), - NumArgs(args.size()) { - - SubExprs = new (C) Stmt*[args.size()+PREARGS_START]; - SubExprs[FN] = fn; - for (unsigned i = 0; i != args.size(); ++i) { - if (args[i]->isTypeDependent()) - ExprBits.TypeDependent = true; - if (args[i]->isValueDependent()) - ExprBits.ValueDependent = true; - if (args[i]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (args[i]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - - SubExprs[i+PREARGS_START] = args[i]; - } - - CallExprBits.NumPreArgs = 0; - RParenLoc = rparenloc; + : CallExpr(C, CallExprClass, fn, /*NumPreArgs=*/0, args, t, VK, rparenloc) { } CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { - // FIXME: Why do we allocate this? - SubExprs = new (C) Stmt*[PREARGS_START]; - CallExprBits.NumPreArgs = 0; -} + : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {} CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty) @@ -1271,16 +1244,21 @@ bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const { return false; } -QualType CallExpr::getCallReturnType() const { - QualType CalleeType = getCallee()->getType(); - if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>()) +QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { + const Expr *Callee = getCallee(); + QualType CalleeType = Callee->getType(); + if (const auto *FnTypePtr = CalleeType->getAs<PointerType>()) { CalleeType = FnTypePtr->getPointeeType(); - else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>()) + } else if (const auto *BPT = CalleeType->getAs<BlockPointerType>()) { CalleeType = BPT->getPointeeType(); - else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) + } else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) { + if (isa<CXXPseudoDestructorExpr>(Callee->IgnoreParens())) + return Ctx.VoidTy; + // This should never be overloaded and so should never return null. - CalleeType = Expr::findBoundMemberType(getCallee()); - + CalleeType = Expr::findBoundMemberType(Callee); + } + const FunctionType *FnType = CalleeType->castAs<FunctionType>(); return FnType->getReturnType(); } @@ -1360,16 +1338,50 @@ IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const { return reinterpret_cast<IdentifierInfo *> (Data & ~(uintptr_t)Mask); } -MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - ValueDecl *memberdecl, - DeclAccessPair founddecl, - DeclarationNameInfo nameinfo, - const TemplateArgumentListInfo *targs, - QualType ty, - ExprValueKind vk, - ExprObjectKind ok) { +UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( + UnaryExprOrTypeTrait ExprKind, Expr *E, QualType resultType, + SourceLocation op, SourceLocation rp) + : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, + false, // Never type-dependent (C++ [temp.dep.expr]p3). + // Value-dependent if the argument is type-dependent. + E->isTypeDependent(), E->isInstantiationDependent(), + E->containsUnexpandedParameterPack()), + OpLoc(op), RParenLoc(rp) { + UnaryExprOrTypeTraitExprBits.Kind = ExprKind; + UnaryExprOrTypeTraitExprBits.IsType = false; + Argument.Ex = E; + + // Check to see if we are in the situation where alignof(decl) should be + // dependent because decl's alignment is dependent. + if (ExprKind == UETT_AlignOf) { + if (!isValueDependent() || !isInstantiationDependent()) { + E = E->IgnoreParens(); + + const ValueDecl *D = nullptr; + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) + D = DRE->getDecl(); + else if (const auto *ME = dyn_cast<MemberExpr>(E)) + D = ME->getMemberDecl(); + + if (D) { + for (const auto *I : D->specific_attrs<AlignedAttr>()) { + if (I->isAlignmentDependent()) { + setValueDependent(true); + setInstantiationDependent(true); + break; + } + } + } + } + } +} + +MemberExpr *MemberExpr::Create( + const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + ValueDecl *memberdecl, DeclAccessPair founddecl, + DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs, + QualType ty, ExprValueKind vk, ExprObjectKind ok) { std::size_t Size = sizeof(MemberExpr); bool hasQualOrFound = (QualifierLoc || @@ -1384,8 +1396,8 @@ MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow, Size += ASTTemplateKWAndArgsInfo::sizeFor(0); void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); - MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, - ty, vk, ok); + MemberExpr *E = new (Mem) + MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok); if (hasQualOrFound) { // FIXME: Wrong. We should be looking at the member declaration we found. @@ -2132,8 +2144,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, case OO_Greater: case OO_GreaterEqual: case OO_LessEqual: - if (Op->getCallReturnType()->isReferenceType() || - Op->getCallReturnType()->isVoidType()) + if (Op->getCallReturnType(Ctx)->isReferenceType() || + Op->getCallReturnType(Ctx)->isVoidType()) break; WarnE = this; Loc = Op->getOperatorLoc(); @@ -2149,12 +2161,16 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // If this is a direct call, get the callee. const CallExpr *CE = cast<CallExpr>(this); if (const Decl *FD = CE->getCalleeDecl()) { + const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD); + bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr() + : FD->hasAttr<WarnUnusedResultAttr>(); + // If the callee has attribute pure, const, or warn_unused_result, warn // about it. void foo() { strlen("bar"); } should warn. // // Note: If new cases are added here, DiagnoseUnusedExprResult should be // updated to match for QoI. - if (FD->hasAttr<WarnUnusedResultAttr>() || + if (HasWarnUnusedResultAttr || FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) { WarnE = this; Loc = CE->getCallee()->getLocStart(); @@ -2200,9 +2216,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } if (const ObjCMethodDecl *MD = ME->getMethodDecl()) - if (MD->hasAttr<WarnUnusedResultAttr>() || - (MD->isPropertyAccessor() && !MD->getReturnType()->isVoidType() && - !ME->getReceiverType()->isObjCIdType())) { + if (MD->hasAttr<WarnUnusedResultAttr>()) { WarnE = this; Loc = getExprLoc(); return true; @@ -2387,7 +2401,7 @@ QualType Expr::findBoundMemberType(const Expr *expr) { return type; } - assert(isa<UnresolvedMemberExpr>(expr)); + assert(isa<UnresolvedMemberExpr>(expr) || isa<CXXPseudoDestructorExpr>(expr)); return QualType(); } @@ -2932,11 +2946,19 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXOperatorCallExprClass: case CXXMemberCallExprClass: case CUDAKernelCallExprClass: + case UserDefinedLiteralClass: { + // We don't know a call definitely has side effects, except for calls + // to pure/const functions that definitely don't. + // If the call itself is considered side-effect free, check the operands. + const Decl *FD = cast<CallExpr>(this)->getCalleeDecl(); + bool IsPure = FD && (FD->hasAttr<ConstAttr>() || FD->hasAttr<PureAttr>()); + if (IsPure || !IncludePossibleEffects) + break; + return true; + } + 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; diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index 9336166..d6f2ce6 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -208,8 +208,9 @@ void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray, } bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const { - return getOperatorNew()->getType()-> - castAs<FunctionProtoType>()->isNothrow(Ctx); + return getOperatorNew()->getType()->castAs<FunctionProtoType>()->isNothrow( + Ctx) && + !getOperatorNew()->isReservedGlobalPlacementOperator(); } // CXXDeleteExpr @@ -237,10 +238,7 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context, SourceLocation ColonColonLoc, SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) : Expr(CXXPseudoDestructorExprClass, - Context.getPointerType(Context.getFunctionType( - Context.VoidTy, None, - FunctionProtoType::ExtProtoInfo( - Context.getDefaultCallingConvention(false, true)))), + Context.BoundMemberTy, VK_RValue, OK_Ordinary, /*isTypeDependent=*/(Base->isTypeDependent() || (DestroyedType.getTypeSourceInfo() && @@ -359,8 +357,7 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, Results = static_cast<DeclAccessPair *>( C.Allocate(sizeof(DeclAccessPair) * NumResults, llvm::alignOf<DeclAccessPair>())); - memcpy(Results, &*Begin.getIterator(), - NumResults * sizeof(DeclAccessPair)); + memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); } // If we have explicit template arguments, check for dependent @@ -401,8 +398,7 @@ void OverloadExpr::initializeResults(const ASTContext &C, C.Allocate(sizeof(DeclAccessPair) * NumResults, llvm::alignOf<DeclAccessPair>())); - memcpy(Results, &*Begin.getIterator(), - NumResults * sizeof(DeclAccessPair)); + memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); } } @@ -1031,6 +1027,11 @@ LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C, return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0); } +bool LambdaExpr::isInitCapture(const LambdaCapture *C) const { + return (C->capturesVariable() && C->getCapturedVar()->isInitCapture() && + (getCallOperator() == C->getCapturedVar()->getDeclContext())); +} + LambdaExpr::capture_iterator LambdaExpr::capture_begin() const { return getLambdaClass()->getLambdaData().Captures; } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index 933ea97..5b320c2 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -283,7 +283,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXMemberCallExprClass: case Expr::UserDefinedLiteralClass: case Expr::CUDAKernelCallExprClass: - return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType()); + return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType(Ctx)); // __builtin_choose_expr is equivalent to the chosen expression. case Expr::ChooseExprClass: @@ -418,9 +418,10 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { islvalue = NTTParm->getType()->isReferenceType(); else islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || - isa<IndirectFieldDecl>(D) || - (Ctx.getLangOpts().CPlusPlus && - (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D))); + isa<IndirectFieldDecl>(D) || + (Ctx.getLangOpts().CPlusPlus && + (isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) || + isa<FunctionTemplateDecl>(D))); return islvalue ? Cl::CL_LValue : Cl::CL_PRValue; } @@ -605,7 +606,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, if (CT.isConstQualified()) return Cl::CM_ConstQualified; if (CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant) - return Cl::CM_ConstQualified; + return Cl::CM_ConstAddrSpace; // Arrays are not modifiable, only their elements are. if (CT->isArrayType()) @@ -671,6 +672,7 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { llvm_unreachable("CM_LValueCast and CL_LValue don't match"); case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty; case Cl::CM_ConstQualified: return MLV_ConstQualified; + case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace; case Cl::CM_ArrayType: return MLV_ArrayType; case Cl::CM_IncompleteType: return MLV_IncompleteType; } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 3d7f2dc..be24a2a 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -1406,7 +1406,7 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, return true; } -const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { +static const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { return LVal.Base.dyn_cast<const ValueDecl*>(); } @@ -2173,7 +2173,7 @@ struct CompleteObject { assert(Value && "missing value for complete object"); } - LLVM_EXPLICIT operator bool() const { return Value; } + explicit operator bool() const { return Value; } }; /// Find the designated sub-object of an rvalue. @@ -2502,8 +2502,9 @@ static bool AreElementsOfSameArray(QualType ObjType, } /// Find the complete object to which an LValue refers. -CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, - const LValue &LVal, QualType LValType) { +static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, + AccessKinds AK, const LValue &LVal, + QualType LValType) { if (!LVal.Base) { Info.Diag(E, diag::note_constexpr_access_null) << AK; return CompleteObject(); @@ -3726,8 +3727,9 @@ static bool HandleFunctionCall(SourceLocation CallLoc, // 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() && - (MD->getParent()->isUnion() || hasFields(MD->getParent()))) { + if (MD && MD->isDefaulted() && + (MD->getParent()->isUnion() || + (MD->isTrivial() && hasFields(MD->getParent())))) { assert(This && (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())); LValue RHS; @@ -3791,11 +3793,9 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, // 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())) && + if (Definition->isDefaulted() && Definition->isCopyOrMoveConstructor() && (Definition->getParent()->isUnion() || - hasFields(Definition->getParent()))) { + (Definition->isTrivial() && hasFields(Definition->getParent())))) { LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); return handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), @@ -4276,6 +4276,9 @@ public: BlockScopeRAII Scope(Info); const CompoundStmt *CS = E->getSubStmt(); + if (CS->body_empty()) + return true; + for (CompoundStmt::const_body_iterator BI = CS->body_begin(), BE = CS->body_end(); /**/; ++BI) { @@ -4301,6 +4304,8 @@ public: return false; } } + + llvm_unreachable("Return from function from the loop above."); } /// Visit a value which is evaluated, but whose value is ignored. @@ -6834,7 +6839,7 @@ void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { } bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { - if (E->isAssignmentOp()) + if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp()) return Error(E); if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E)) @@ -6846,7 +6851,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) { ComplexValue LHS, RHS; bool LHSOK; - if (E->getLHS()->getType()->isRealFloatingType()) { + if (E->isAssignmentOp()) { + LValue LV; + EvaluateLValue(E->getLHS(), LV, Info); + LHSOK = false; + } else if (LHSTy->isRealFloatingType()) { LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info); if (LHSOK) { LHS.makeComplexFloat(); @@ -7586,10 +7595,23 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, else if (S->getString().getAsInteger(0, fill)) return false; - if (SNaN) - Result = llvm::APFloat::getSNaN(Sem, false, &fill); - else - Result = llvm::APFloat::getQNaN(Sem, false, &fill); + if (Context.getTargetInfo().isNan2008()) { + if (SNaN) + Result = llvm::APFloat::getSNaN(Sem, false, &fill); + else + Result = llvm::APFloat::getQNaN(Sem, false, &fill); + } else { + // Prior to IEEE 754-2008, architectures were allowed to choose whether + // the first bit of their significand was set for qNaN or sNaN. MIPS chose + // a different encoding to what became a standard in 2008, and for pre- + // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as + // sNaN. This is now known as "legacy NaN" encoding. + if (SNaN) + Result = llvm::APFloat::getQNaN(Sem, false, &fill); + else + Result = llvm::APFloat::getSNaN(Sem, false, &fill); + } + return true; } diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp index 8894107..730842a 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp @@ -66,6 +66,11 @@ Stmt *ExternalASTSource::GetExternalDeclStmt(uint64_t Offset) { return nullptr; } +CXXCtorInitializer ** +ExternalASTSource::GetExternalCXXCtorInitializers(uint64_t Offset) { + return nullptr; +} + CXXBaseSpecifier * ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { return nullptr; diff --git a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp index eb3020c..0b82da1 100644 --- a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp +++ b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp @@ -22,11 +22,9 @@ #include "llvm/Support/raw_ostream.h" #include <map> #include <set> +using namespace clang; -using namespace llvm; - -namespace clang { - +namespace { /// InheritanceHierarchyWriter - Helper class that writes out a /// GraphViz file that diagrams the inheritance hierarchy starting at /// a given C++ class type. Note that we do not use LLVM's @@ -44,7 +42,8 @@ public: : Context(Context), Out(Out) { } void WriteGraph(QualType Type) { - Out << "digraph \"" << DOT::EscapeString(Type.getAsString()) << "\" {\n"; + Out << "digraph \"" << llvm::DOT::EscapeString(Type.getAsString()) + << "\" {\n"; WriteNode(Type, false); Out << "}\n"; } @@ -59,6 +58,7 @@ protected: /// (only) virtual base. raw_ostream& WriteNodeReference(QualType Type, bool FromVirtual); }; +} // namespace void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) { QualType CanonType = Context.getCanonicalType(Type); @@ -78,7 +78,7 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) { // Give the node a label based on the name of the class. std::string TypeName = Type.getAsString(); - Out << " [ shape=\"box\", label=\"" << DOT::EscapeString(TypeName); + Out << " [ shape=\"box\", label=\"" << llvm::DOT::EscapeString(TypeName); // If the name of the class was a typedef or something different // from the "real" class name, show the real class name in @@ -139,9 +139,8 @@ void CXXRecordDecl::viewInheritance(ASTContext& Context) const { int FD; SmallString<128> Filename; - std::error_code EC = - sys::fs::createTemporaryFile(Self.getAsString(), "dot", FD, Filename); - if (EC) { + if (std::error_code EC = llvm::sys::fs::createTemporaryFile( + Self.getAsString(), "dot", FD, Filename)) { llvm::errs() << "Error: " << EC.message() << "\n"; return; } @@ -159,5 +158,3 @@ void CXXRecordDecl::viewInheritance(ASTContext& Context) const { // Display the graph DisplayGraph(Filename); } - -} diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index 378121c..7503cbf 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -106,7 +106,7 @@ public: TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0); uint64_t Width = Target.getTypeWidth(PtrDiff); unsigned Align = Target.getTypeAlign(PtrDiff); - if (MPT->getPointeeType()->isFunctionType()) + if (MPT->isMemberFunctionPointer()) Width = 2 * Width; return std::make_pair(Width, Align); } @@ -133,6 +133,22 @@ public: return Layout.getNonVirtualSize() == PointerSize; } + const CXXConstructorDecl * + getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { + return nullptr; + } + + void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, + CXXConstructorDecl *CD) override {} + + void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx, Expr *DAE) override {} + + Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx) override { + return nullptr; + } + MangleNumberingContext *createMangleNumberingContext() const override { return new ItaniumNumberingContext(); } diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 156ad64..d07efae 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -42,8 +42,8 @@ using namespace clang; namespace { -/// \brief Retrieve the declaration context that should be used when mangling -/// the given declaration. +/// Retrieve the declaration context that should be used when mangling the given +/// declaration. static const DeclContext *getEffectiveDeclContext(const Decl *D) { // The ABI assumes that lambda closure types that occur within // default arguments live in the context of the function. However, due to @@ -69,6 +69,14 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC)) return getEffectiveDeclContext(CD); + if (const auto *VD = dyn_cast<VarDecl>(D)) + if (VD->isExternC()) + return VD->getASTContext().getTranslationUnitDecl(); + + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isExternC()) + return FD->getASTContext().getTranslationUnitDecl(); + return DC; } @@ -156,12 +164,18 @@ public: void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override; void mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &Out) override; + void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl, + raw_ostream &Out) override; + void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl, + raw_ostream &Out) override; void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override; void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &) override; void mangleStringLiteral(const StringLiteral *, raw_ostream &) override; + void mangleCXXVTableBitSet(const CXXRecordDecl *RD, raw_ostream &) override; + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { // Lambda closure types are already numbered. if (isLambda(ND)) @@ -196,7 +210,7 @@ public: /// @} }; -/// CXXNameMangler - Manage the mangling of a single name. +/// Manage the mangling of a single name. class CXXNameMangler { ItaniumMangleContextImpl &Context; raw_ostream &Out; @@ -207,7 +221,7 @@ class CXXNameMangler { const NamedDecl *Structor; unsigned StructorType; - /// SeqID - The next subsitution sequence number. + /// The next substitution sequence number. unsigned SeqID; class FunctionTypeDepthState { @@ -284,7 +298,7 @@ public: #endif raw_ostream &getStream() { return Out; } - void mangle(const NamedDecl *D, StringRef Prefix = "_Z"); + void mangle(const NamedDecl *D); void mangleCallOffset(int64_t NonVirtual, int64_t Virtual); void mangleNumber(const llvm::APSInt &I); void mangleNumber(int64_t Number); @@ -317,10 +331,8 @@ private: void addSubstitution(uintptr_t Ptr); void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, - NamedDecl *firstQualifierLookup, bool recursive = false); void mangleUnresolvedName(NestedNameSpecifier *qualifier, - NamedDecl *firstQualifierLookup, DeclarationName name, unsigned KnownArity = UnknownArity); @@ -350,6 +362,9 @@ private: void manglePrefix(QualType type); void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false); void mangleTemplatePrefix(TemplateName Template); + bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType, + StringRef Prefix = ""); + void mangleOperatorName(DeclarationName Name, unsigned Arity); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleQualifiers(Qualifiers Quals); void mangleRefQualifier(RefQualifierKind RefQualifier); @@ -370,12 +385,14 @@ private: void mangleAArch64NeonVectorType(const VectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); + void mangleMemberExprBase(const Expr *base, bool isArrow); void mangleMemberExpr(const Expr *base, bool isArrow, NestedNameSpecifier *qualifier, NamedDecl *firstQualifierLookup, DeclarationName name, unsigned knownArity); void mangleCastExpression(const Expr *E, StringRef CastEncoding); + void mangleInitListElements(const InitListExpr *InitList); void mangleExpression(const Expr *E, unsigned Arity = UnknownArity); void mangleCXXCtorType(CXXCtorType T); void mangleCXXDtorType(CXXDtorType T); @@ -439,11 +456,11 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { return true; } -void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { +void CXXNameMangler::mangle(const NamedDecl *D) { // <mangled-name> ::= _Z <encoding> // ::= <data name> // ::= <special-name> - Out << Prefix; + Out << "_Z"; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) mangleFunctionEncoding(FD); else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) @@ -519,7 +536,7 @@ static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { return DC; } -/// isStd - Return whether a given namespace is the 'std' namespace. +/// Return whether a given namespace is the 'std' namespace. static bool isStd(const NamespaceDecl *NS) { if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS)) ->isTranslationUnit()) @@ -748,8 +765,7 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) { } void CXXNameMangler::manglePrefix(QualType type) { - if (const TemplateSpecializationType *TST = - type->getAs<TemplateSpecializationType>()) { + if (const auto *TST = type->getAs<TemplateSpecializationType>()) { if (!mangleSubstitution(QualType(TST, 0))) { mangleTemplatePrefix(TST->getTemplateName()); @@ -759,17 +775,19 @@ void CXXNameMangler::manglePrefix(QualType type) { mangleTemplateArgs(TST->getArgs(), TST->getNumArgs()); addSubstitution(QualType(TST, 0)); } - } else if (const DependentTemplateSpecializationType *DTST - = type->getAs<DependentTemplateSpecializationType>()) { - TemplateName Template - = getASTContext().getDependentTemplateName(DTST->getQualifier(), - DTST->getIdentifier()); - mangleTemplatePrefix(Template); + } else if (const auto *DTST = + type->getAs<DependentTemplateSpecializationType>()) { + if (!mangleSubstitution(QualType(DTST, 0))) { + TemplateName Template = getASTContext().getDependentTemplateName( + DTST->getQualifier(), DTST->getIdentifier()); + mangleTemplatePrefix(Template); - // FIXME: GCC does not appear to mangle the template arguments when - // the template in question is a dependent template name. Should we - // emulate that badness? - mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs()); + // FIXME: GCC does not appear to mangle the template arguments when + // the template in question is a dependent template name. Should we + // emulate that badness? + mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs()); + addSubstitution(QualType(DTST, 0)); + } } else { // We use the QualType mangle type variant here because it handles // substitutions. @@ -779,12 +797,9 @@ void CXXNameMangler::manglePrefix(QualType type) { /// Mangle everything prior to the base-unresolved-name in an unresolved-name. /// -/// \param firstQualifierLookup - the entity found by unqualified lookup -/// for the first name in the qualifier, if this is for a member expression /// \param recursive - true if this is being called recursively, /// i.e. if there is more prefix "to the right". void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, - NamedDecl *firstQualifierLookup, bool recursive) { // x, ::x @@ -817,7 +832,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, case NestedNameSpecifier::Namespace: if (qualifier->getPrefix()) - mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); else Out << "sr"; @@ -825,7 +840,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, break; case NestedNameSpecifier::NamespaceAlias: if (qualifier->getPrefix()) - mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); else Out << "sr"; @@ -842,193 +857,26 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, // - a template template parameter with arguments // In all of these cases, we should have no prefix. if (qualifier->getPrefix()) { - mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); } else { // Otherwise, all the cases want this. Out << "sr"; } - // Only certain other types are valid as prefixes; enumerate them. - switch (type->getTypeClass()) { - case Type::Builtin: - case Type::Complex: - case Type::Adjusted: - case Type::Decayed: - case Type::Pointer: - case Type::BlockPointer: - case Type::LValueReference: - case Type::RValueReference: - case Type::MemberPointer: - case Type::ConstantArray: - case Type::IncompleteArray: - case Type::VariableArray: - case Type::DependentSizedArray: - case Type::DependentSizedExtVector: - case Type::Vector: - case Type::ExtVector: - case Type::FunctionProto: - case Type::FunctionNoProto: - case Type::Enum: - case Type::Paren: - case Type::Elaborated: - case Type::Attributed: - case Type::Auto: - case Type::PackExpansion: - case Type::ObjCObject: - case Type::ObjCInterface: - case Type::ObjCObjectPointer: - case Type::Atomic: - llvm_unreachable("type is illegal as a nested name specifier"); - - case Type::SubstTemplateTypeParmPack: - // FIXME: not clear how to mangle this! - // template <class T...> class A { - // template <class U...> void foo(decltype(T::foo(U())) x...); - // }; - Out << "_SUBSTPACK_"; - break; - - // <unresolved-type> ::= <template-param> - // ::= <decltype> - // ::= <template-template-param> <template-args> - // (this last is not official yet) - case Type::TypeOfExpr: - case Type::TypeOf: - case Type::Decltype: - case Type::TemplateTypeParm: - case Type::UnaryTransform: - case Type::SubstTemplateTypeParm: - unresolvedType: - assert(!qualifier->getPrefix()); - - // We only get here recursively if we're followed by identifiers. - if (recursive) Out << 'N'; - - // This seems to do everything we want. It's not really - // sanctioned for a substituted template parameter, though. - mangleType(QualType(type, 0)); - - // We never want to print 'E' directly after an unresolved-type, - // so we return directly. + if (mangleUnresolvedTypeOrSimpleId(QualType(type, 0), recursive ? "N" : "")) return; - case Type::Typedef: - mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier()); - break; - - case Type::UnresolvedUsing: - mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl() - ->getIdentifier()); - break; - - case Type::Record: - mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier()); - break; - - case Type::TemplateSpecialization: { - const TemplateSpecializationType *tst - = cast<TemplateSpecializationType>(type); - TemplateName name = tst->getTemplateName(); - switch (name.getKind()) { - case TemplateName::Template: - case TemplateName::QualifiedTemplate: { - TemplateDecl *temp = name.getAsTemplateDecl(); - - // If the base is a template template parameter, this is an - // unresolved type. - assert(temp && "no template for template specialization type"); - if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType; - - mangleSourceName(temp->getIdentifier()); - break; - } - - case TemplateName::OverloadedTemplate: - case TemplateName::DependentTemplate: - llvm_unreachable("invalid base for a template specialization type"); - - case TemplateName::SubstTemplateTemplateParm: { - SubstTemplateTemplateParmStorage *subst - = name.getAsSubstTemplateTemplateParm(); - mangleExistingSubstitution(subst->getReplacement()); - break; - } - - case TemplateName::SubstTemplateTemplateParmPack: { - // FIXME: not clear how to mangle this! - // template <template <class U> class T...> class A { - // template <class U...> void foo(decltype(T<U>::foo) x...); - // }; - Out << "_SUBSTPACK_"; - break; - } - } - - mangleTemplateArgs(tst->getArgs(), tst->getNumArgs()); - break; - } - - case Type::InjectedClassName: - mangleSourceName(cast<InjectedClassNameType>(type)->getDecl() - ->getIdentifier()); - break; - - case Type::DependentName: - mangleSourceName(cast<DependentNameType>(type)->getIdentifier()); - break; - - case Type::DependentTemplateSpecialization: { - const DependentTemplateSpecializationType *tst - = cast<DependentTemplateSpecializationType>(type); - mangleSourceName(tst->getIdentifier()); - mangleTemplateArgs(tst->getArgs(), tst->getNumArgs()); - break; - } - } break; } case NestedNameSpecifier::Identifier: // Member expressions can have these without prefixes. - if (qualifier->getPrefix()) { - mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + if (qualifier->getPrefix()) + mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); - } else if (firstQualifierLookup) { - - // Try to make a proper qualifier out of the lookup result, and - // then just recurse on that. - NestedNameSpecifier *newQualifier; - if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) { - QualType type = getASTContext().getTypeDeclType(typeDecl); - - // Pretend we had a different nested name specifier. - newQualifier = NestedNameSpecifier::Create(getASTContext(), - /*prefix*/ nullptr, - /*template*/ false, - type.getTypePtr()); - } else if (NamespaceDecl *nspace = - dyn_cast<NamespaceDecl>(firstQualifierLookup)) { - newQualifier = NestedNameSpecifier::Create(getASTContext(), - /*prefix*/ nullptr, - nspace); - } else if (NamespaceAliasDecl *alias = - dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) { - newQualifier = NestedNameSpecifier::Create(getASTContext(), - /*prefix*/ nullptr, - alias); - } else { - // No sensible mangling to do here. - newQualifier = nullptr; - } - - if (newQualifier) - return mangleUnresolvedPrefix(newQualifier, /*lookup*/ nullptr, - recursive); - - } else { + else Out << "sr"; - } mangleSourceName(qualifier->getAsIdentifier()); break; @@ -1043,16 +891,41 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, /// Mangle an unresolved-name, which is generally used for names which /// weren't resolved to specific entities. void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, - NamedDecl *firstQualifierLookup, DeclarationName name, unsigned knownArity) { - if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup); - mangleUnqualifiedName(nullptr, name, knownArity); + if (qualifier) mangleUnresolvedPrefix(qualifier); + switch (name.getNameKind()) { + // <base-unresolved-name> ::= <simple-id> + case DeclarationName::Identifier: + mangleSourceName(name.getAsIdentifierInfo()); + break; + // <base-unresolved-name> ::= dn <destructor-name> + case DeclarationName::CXXDestructorName: + Out << "dn"; + mangleUnresolvedTypeOrSimpleId(name.getCXXNameType()); + break; + // <base-unresolved-name> ::= on <operator-name> + case DeclarationName::CXXConversionFunctionName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXOperatorName: + Out << "on"; + mangleOperatorName(name, knownArity); + break; + case DeclarationName::CXXConstructorName: + llvm_unreachable("Can't mangle a constructor name!"); + case DeclarationName::CXXUsingDirective: + llvm_unreachable("Can't mangle a using directive name!"); + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCZeroArgSelector: + llvm_unreachable("Can't mangle Objective-C selector names here!"); + } } void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, unsigned KnownArity) { + unsigned Arity = KnownArity; // <unqualified-name> ::= <operator-name> // ::= <ctor-dtor-name> // ::= <source-name> @@ -1163,7 +1036,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, Str += llvm::utostr(AnonStructId); Out << Str.size(); - Out << Str.str(); + Out << Str; break; } @@ -1194,33 +1067,19 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, mangleCXXDtorType(Dtor_Complete); break; - case DeclarationName::CXXConversionFunctionName: - // <operator-name> ::= cv <type> # (cast) - Out << "cv"; - mangleType(Name.getCXXNameType()); - break; - - case DeclarationName::CXXOperatorName: { - unsigned Arity; - if (ND) { + case DeclarationName::CXXOperatorName: + if (ND && Arity == UnknownArity) { Arity = cast<FunctionDecl>(ND)->getNumParams(); - // If we have a C++ member function, we need to include the 'this' pointer. - // FIXME: This does not make sense for operators that are static, but their - // names stay the same regardless of the arity (operator new for instance). - if (isa<CXXMethodDecl>(ND)) - Arity++; - } else - Arity = KnownArity; - - mangleOperatorName(Name.getCXXOverloadedOperator(), Arity); - break; - } - + // If we have a member function, we need to include the 'this' pointer. + if (const auto *MD = dyn_cast<CXXMethodDecl>(ND)) + if (!MD->isStatic()) + Arity++; + } + // FALLTHROUGH + case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXLiteralOperatorName: - // FIXME: This mangling is not yet official. - Out << "li"; - mangleSourceName(Name.getCXXLiteralIdentifier()); + mangleOperatorName(Name, Arity); break; case DeclarationName::CXXUsingDirective: @@ -1529,7 +1388,8 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); assert(Dependent && "Unknown template name kind?"); - manglePrefix(Dependent->getQualifier()); + if (NestedNameSpecifier *Qualifier = Dependent->getQualifier()) + manglePrefix(Qualifier); mangleUnscopedTemplateName(Template); } @@ -1591,7 +1451,7 @@ void CXXNameMangler::mangleType(TemplateName TN) { // <class-enum-type> ::= <name> // <name> ::= <nested-name> - mangleUnresolvedPrefix(Dependent->getQualifier(), nullptr); + mangleUnresolvedPrefix(Dependent->getQualifier()); mangleSourceName(Dependent->getIdentifier()); break; } @@ -1620,6 +1480,181 @@ void CXXNameMangler::mangleType(TemplateName TN) { addSubstitution(TN); } +bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, + StringRef Prefix) { + // Only certain other types are valid as prefixes; enumerate them. + switch (Ty->getTypeClass()) { + case Type::Builtin: + case Type::Complex: + case Type::Adjusted: + case Type::Decayed: + case Type::Pointer: + case Type::BlockPointer: + case Type::LValueReference: + case Type::RValueReference: + case Type::MemberPointer: + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + case Type::DependentSizedExtVector: + case Type::Vector: + case Type::ExtVector: + case Type::FunctionProto: + case Type::FunctionNoProto: + case Type::Paren: + case Type::Attributed: + case Type::Auto: + case Type::PackExpansion: + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + case Type::Atomic: + llvm_unreachable("type is illegal as a nested name specifier"); + + case Type::SubstTemplateTypeParmPack: + // FIXME: not clear how to mangle this! + // template <class T...> class A { + // template <class U...> void foo(decltype(T::foo(U())) x...); + // }; + Out << "_SUBSTPACK_"; + break; + + // <unresolved-type> ::= <template-param> + // ::= <decltype> + // ::= <template-template-param> <template-args> + // (this last is not official yet) + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::Decltype: + case Type::TemplateTypeParm: + case Type::UnaryTransform: + case Type::SubstTemplateTypeParm: + unresolvedType: + // Some callers want a prefix before the mangled type. + Out << Prefix; + + // This seems to do everything we want. It's not really + // sanctioned for a substituted template parameter, though. + mangleType(Ty); + + // We never want to print 'E' directly after an unresolved-type, + // so we return directly. + return true; + + case Type::Typedef: + mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier()); + break; + + case Type::UnresolvedUsing: + mangleSourceName( + cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier()); + break; + + case Type::Enum: + case Type::Record: + mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier()); + break; + + case Type::TemplateSpecialization: { + const TemplateSpecializationType *TST = + cast<TemplateSpecializationType>(Ty); + TemplateName TN = TST->getTemplateName(); + switch (TN.getKind()) { + case TemplateName::Template: + case TemplateName::QualifiedTemplate: { + TemplateDecl *TD = TN.getAsTemplateDecl(); + + // If the base is a template template parameter, this is an + // unresolved type. + assert(TD && "no template for template specialization type"); + if (isa<TemplateTemplateParmDecl>(TD)) + goto unresolvedType; + + mangleSourceName(TD->getIdentifier()); + break; + } + + case TemplateName::OverloadedTemplate: + case TemplateName::DependentTemplate: + llvm_unreachable("invalid base for a template specialization type"); + + case TemplateName::SubstTemplateTemplateParm: { + SubstTemplateTemplateParmStorage *subst = + TN.getAsSubstTemplateTemplateParm(); + mangleExistingSubstitution(subst->getReplacement()); + break; + } + + case TemplateName::SubstTemplateTemplateParmPack: { + // FIXME: not clear how to mangle this! + // template <template <class U> class T...> class A { + // template <class U...> void foo(decltype(T<U>::foo) x...); + // }; + Out << "_SUBSTPACK_"; + break; + } + } + + mangleTemplateArgs(TST->getArgs(), TST->getNumArgs()); + break; + } + + case Type::InjectedClassName: + mangleSourceName( + cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier()); + break; + + case Type::DependentName: + mangleSourceName(cast<DependentNameType>(Ty)->getIdentifier()); + break; + + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *DTST = + cast<DependentTemplateSpecializationType>(Ty); + mangleSourceName(DTST->getIdentifier()); + mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs()); + break; + } + + case Type::Elaborated: + return mangleUnresolvedTypeOrSimpleId( + cast<ElaboratedType>(Ty)->getNamedType(), Prefix); + } + + return false; +} + +void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) { + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXUsingDirective: + case DeclarationName::Identifier: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCZeroArgSelector: + llvm_unreachable("Not an operator name"); + + case DeclarationName::CXXConversionFunctionName: + // <operator-name> ::= cv <type> # (cast) + Out << "cv"; + mangleType(Name.getCXXNameType()); + break; + + case DeclarationName::CXXLiteralOperatorName: + Out << "li"; + mangleSourceName(Name.getCXXLiteralIdentifier()); + return; + + case DeclarationName::CXXOperatorName: + mangleOperatorName(Name.getCXXOverloadedOperator(), Arity); + break; + } +} + + + void CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { switch (OO) { @@ -2276,6 +2311,7 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { EltName = "Poly16"; break; case BuiltinType::ULong: + case BuiltinType::ULongLong: EltName = "Poly64"; break; default: @@ -2519,6 +2555,29 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T, } +void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) { + // 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 + // does not specify anything here, so we follow GCC. + Out << "dtdefpT"; + } else { + Out << (IsArrow ? "pt" : "dt"); + mangleExpression(Base); + } +} + /// Mangles a member expression. void CXXNameMangler::mangleMemberExpr(const Expr *base, bool isArrow, @@ -2528,30 +2587,9 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base, unsigned arity) { // <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 - // does not specify anything here, so we follow GCC. - Out << "dtdefpT"; - } else { - Out << (isArrow ? "pt" : "dt"); - mangleExpression(base); - } - } - mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity); + if (base) + mangleMemberExprBase(base, isArrow); + mangleUnresolvedName(qualifier, member, arity); } /// Look at the callee of the given call expression and determine if @@ -2592,6 +2630,13 @@ void CXXNameMangler::mangleCastExpression(const Expr *E, StringRef CastEncoding) mangleExpression(ECE->getSubExpr()); } +void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) { + if (auto *Syntactic = InitList->getSyntacticForm()) + InitList = Syntactic; + for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i) + mangleExpression(InitList->getInit(i)); +} + void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { // <expression> ::= <unary operator-name> <expression> // ::= <binary operator-name> <expression> <expression> @@ -2631,7 +2676,6 @@ recurse: // These all can only appear in local or variable-initialization // contexts and so should never appear in a mangling. case Expr::AddrLabelExprClass: - case Expr::DesignatedInitExprClass: case Expr::ImplicitValueInitExprClass: case Expr::ParenListExprClass: case Expr::LambdaExprClass: @@ -2641,9 +2685,9 @@ recurse: // FIXME: invent manglings for all these. case Expr::BlockExprClass: - case Expr::CXXPseudoDestructorExprClass: case Expr::ChooseExprClass: case Expr::CompoundLiteralExprClass: + case Expr::DesignatedInitExprClass: case Expr::ExtVectorElementExprClass: case Expr::GenericSelectionExprClass: case Expr::ObjCEncodeExprClass: @@ -2713,9 +2757,7 @@ recurse: case Expr::InitListExprClass: { Out << "il"; - const InitListExpr *InitList = cast<InitListExpr>(E); - for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i) - mangleExpression(InitList->getInit(i)); + mangleInitListElements(cast<InitListExpr>(E)); Out << "E"; break; } @@ -2759,9 +2801,14 @@ recurse: Out << "cl"; } - mangleExpression(CE->getCallee(), CE->getNumArgs()); - for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I) - mangleExpression(CE->getArg(I)); + unsigned CallArity = CE->getNumArgs(); + for (const Expr *Arg : CE->arguments()) + if (isa<PackExpansionExpr>(Arg)) + CallArity = UnknownArity; + + mangleExpression(CE->getCallee(), CallArity); + for (const Expr *Arg : CE->arguments()) + mangleExpression(Arg); Out << 'E'; break; } @@ -2793,9 +2840,7 @@ recurse: } else if (New->getInitializationStyle() == CXXNewExpr::ListInit && isa<InitListExpr>(Init)) { // Only take InitListExprs apart for list-initialization. - const InitListExpr *InitList = cast<InitListExpr>(Init); - for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i) - mangleExpression(InitList->getInit(i)); + mangleInitListElements(cast<InitListExpr>(Init)); } else mangleExpression(Init); } @@ -2803,6 +2848,33 @@ recurse: break; } + case Expr::CXXPseudoDestructorExprClass: { + const auto *PDE = cast<CXXPseudoDestructorExpr>(E); + if (const Expr *Base = PDE->getBase()) + mangleMemberExprBase(Base, PDE->isArrow()); + NestedNameSpecifier *Qualifier = PDE->getQualifier(); + QualType ScopeType; + if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) { + if (Qualifier) { + mangleUnresolvedPrefix(Qualifier, + /*Recursive=*/true); + mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()); + Out << 'E'; + } else { + Out << "sr"; + if (!mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType())) + Out << 'E'; + } + } else if (Qualifier) { + mangleUnresolvedPrefix(Qualifier); + } + // <base-unresolved-name> ::= dn <destructor-name> + Out << "dn"; + QualType DestroyedType = PDE->getDestroyedType(); + mangleUnresolvedTypeOrSimpleId(DestroyedType); + break; + } + case Expr::MemberExprClass: { const MemberExpr *ME = cast<MemberExpr>(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), @@ -2813,9 +2885,9 @@ recurse: case Expr::UnresolvedMemberExprClass: { const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E); - mangleMemberExpr(ME->getBase(), ME->isArrow(), - ME->getQualifier(), nullptr, ME->getMemberName(), - Arity); + mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), + ME->isArrow(), ME->getQualifier(), nullptr, + ME->getMemberName(), Arity); if (ME->hasExplicitTemplateArgs()) mangleTemplateArgs(ME->getExplicitTemplateArgs()); break; @@ -2824,8 +2896,9 @@ recurse: case Expr::CXXDependentScopeMemberExprClass: { const CXXDependentScopeMemberExpr *ME = cast<CXXDependentScopeMemberExpr>(E); - mangleMemberExpr(ME->getBase(), ME->isArrow(), - ME->getQualifier(), ME->getFirstQualifierFoundInScope(), + mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), + ME->isArrow(), ME->getQualifier(), + ME->getFirstQualifierFoundInScope(), ME->getMember(), Arity); if (ME->hasExplicitTemplateArgs()) mangleTemplateArgs(ME->getExplicitTemplateArgs()); @@ -2834,7 +2907,7 @@ recurse: case Expr::UnresolvedLookupExprClass: { const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E); - mangleUnresolvedName(ULE->getQualifier(), nullptr, ULE->getName(), Arity); + mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity); // All the <unresolved-name> productions end in a // base-unresolved-name, where <template-args> are just tacked @@ -2856,26 +2929,55 @@ recurse: break; } - case Expr::CXXTemporaryObjectExprClass: case Expr::CXXConstructExprClass: { - const CXXConstructExpr *CE = cast<CXXConstructExpr>(E); + const auto *CE = cast<CXXConstructExpr>(E); + if (!CE->isListInitialization() || CE->isStdInitListInitialization()) { + assert( + CE->getNumArgs() >= 1 && + (CE->getNumArgs() == 1 || isa<CXXDefaultArgExpr>(CE->getArg(1))) && + "implicit CXXConstructExpr must have one argument"); + return mangleExpression(cast<CXXConstructExpr>(E)->getArg(0)); + } + Out << "il"; + for (auto *E : CE->arguments()) + mangleExpression(E); + Out << "E"; + break; + } + + case Expr::CXXTemporaryObjectExprClass: { + const auto *CE = cast<CXXTemporaryObjectExpr>(E); unsigned N = CE->getNumArgs(); + bool List = CE->isListInitialization(); - if (CE->isListInitialization()) + if (List) Out << "tl"; else Out << "cv"; mangleType(CE->getType()); - if (N != 1) Out << '_'; - for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I)); - if (N != 1) Out << 'E'; + if (!List && N != 1) + Out << '_'; + if (CE->isStdInitListInitialization()) { + // We implicitly created a std::initializer_list<T> for the first argument + // of a constructor of type U in an expression of the form U{a, b, c}. + // Strip all the semantic gunk off the initializer list. + auto *SILE = + cast<CXXStdInitializerListExpr>(CE->getArg(0)->IgnoreImplicit()); + auto *ILE = cast<InitListExpr>(SILE->getSubExpr()->IgnoreImplicit()); + mangleInitListElements(ILE); + } else { + for (auto *E : CE->arguments()) + mangleExpression(E); + } + if (List || N != 1) + Out << 'E'; break; } case Expr::CXXScalarValueInitExprClass: - Out <<"cv"; + Out << "cv"; mangleType(E->getType()); - Out <<"_E"; + Out << "_E"; break; case Expr::CXXNoexceptExprClass: @@ -3020,10 +3122,28 @@ recurse: // Fall through to mangle the cast itself. case Expr::CStyleCastExprClass: - case Expr::CXXFunctionalCastExprClass: mangleCastExpression(E, "cv"); break; + case Expr::CXXFunctionalCastExprClass: { + auto *Sub = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreImplicit(); + // FIXME: Add isImplicit to CXXConstructExpr. + if (auto *CCE = dyn_cast<CXXConstructExpr>(Sub)) + if (CCE->getParenOrBraceRange().isInvalid()) + Sub = CCE->getArg(0)->IgnoreImplicit(); + if (auto *StdInitList = dyn_cast<CXXStdInitializerListExpr>(Sub)) + Sub = StdInitList->getSubExpr()->IgnoreImplicit(); + if (auto *IL = dyn_cast<InitListExpr>(Sub)) { + Out << "tl"; + mangleType(E->getType()); + mangleInitListElements(IL); + Out << "E"; + } else { + mangleCastExpression(E, "cv"); + } + break; + } + case Expr::CXXStaticCastExprClass: mangleCastExpression(E, "sc"); break; @@ -3058,7 +3178,7 @@ recurse: default: // <expr-primary> ::= L <mangled-name> E # external name Out << 'L'; - mangle(D, "_Z"); + mangle(D); Out << 'E'; break; @@ -3101,8 +3221,7 @@ recurse: case Expr::DependentScopeDeclRefExprClass: { const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E); - mangleUnresolvedName(DRE->getQualifier(), nullptr, DRE->getDeclName(), - Arity); + mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity); // All the <unresolved-name> productions end in a // base-unresolved-name, where <template-args> are just tacked @@ -3327,6 +3446,9 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) { case Ctor_Comdat: Out << "C5"; break; + case Ctor_DefaultClosure: + case Ctor_CopyingClosure: + llvm_unreachable("closure constructors don't exist for the Itanium ABI!"); } } @@ -3410,8 +3532,8 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) { if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { const ValueDecl *D = DRE->getDecl(); if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) { - Out << "L"; - mangle(D, "_Z"); + Out << 'L'; + mangle(D); Out << 'E'; break; } @@ -3440,13 +3562,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) { Out << 'L'; // References to external entities use the mangled name; if the name would // not normally be manged then mangle it as unqualified. - // - // FIXME: The ABI specifies that external names here should have _Z, but - // gcc leaves this off. - if (compensateMangling) - mangle(D, "_Z"); - else - mangle(D, "Z"); + mangle(D); Out << 'E'; if (compensateMangling) @@ -3524,8 +3640,8 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { return mangleSubstitution(reinterpret_cast<uintptr_t>(ND)); } -/// \brief Determine whether the given type has any qualifiers that are -/// relevant for substitutions. +/// Determine whether the given type has any qualifiers that are relevant for +/// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { Qualifiers Qs = T.getQualifiers(); return Qs.getCVRQualifiers() || Qs.hasAddressSpace(); @@ -3571,8 +3687,8 @@ static bool isCharType(QualType T) { T->isSpecificBuiltinType(BuiltinType::Char_U); } -/// isCharSpecialization - Returns whether a given type is a template -/// specialization of a given name with a single argument of type char. +/// Returns whether a given type is a template specialization of a given name +/// with a single argument of type char. static bool isCharSpecialization(QualType T, const char *Name) { if (T.isNull()) return false; @@ -3722,8 +3838,8 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { // -/// \brief Mangles the name of the declaration D and emits that name to the -/// given output stream. +/// Mangles the name of the declaration D and emits that name to the given +/// output stream. /// /// If the declaration D requires a mangled name, this routine will emit that /// mangled name to \p os and return true. Otherwise, \p os will be unchanged @@ -3815,8 +3931,7 @@ void ItaniumMangleContextImpl::mangleCXXDtorThunk( Mangler.mangleFunctionEncoding(DD); } -/// mangleGuardVariable - Returns the mangled name for a guard variable -/// for the passed in VarDecl. +/// Returns the mangled name for a guard variable for the passed in VarDecl. void ItaniumMangleContextImpl::mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) { // <special-name> ::= GV <object name> # Guard variable for one-time @@ -3845,6 +3960,26 @@ void ItaniumMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D, Mangler.getStream() << D->getName(); } +void ItaniumMangleContextImpl::mangleSEHFilterExpression( + const NamedDecl *EnclosingDecl, raw_ostream &Out) { + CXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "__filt_"; + if (shouldMangleDeclName(EnclosingDecl)) + Mangler.mangle(EnclosingDecl); + else + Mangler.getStream() << EnclosingDecl->getName(); +} + +void ItaniumMangleContextImpl::mangleSEHFinallyBlock( + const NamedDecl *EnclosingDecl, raw_ostream &Out) { + CXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "__fin_"; + if (shouldMangleDeclName(EnclosingDecl)) + Mangler.mangle(EnclosingDecl); + else + Mangler.getStream() << EnclosingDecl->getName(); +} + void ItaniumMangleContextImpl::mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &Out) { // <special-name> ::= TH <object name> @@ -3923,6 +4058,22 @@ void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) { mangleCXXRTTIName(Ty, Out); } +void ItaniumMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD, + raw_ostream &Out) { + Linkage L = RD->getLinkageInternal(); + if (L == InternalLinkage || L == UniqueExternalLinkage) { + // This part of the identifier needs to be unique across all translation + // units in the linked program. The scheme fails if multiple translation + // units are compiled using the same relative source file path, or if + // multiple translation units are built from the same source file. + SourceManager &SM = getASTContext().getSourceManager(); + Out << "[" << SM.getFileEntryForID(SM.getMainFileID())->getName() << "]"; + } + + CXXNameMangler Mangler(*this, Out); + Mangler.mangleType(QualType(RD->getTypeForDecl(), 0)); +} + void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) { llvm_unreachable("Can't mangle string literals"); } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp index 0603d3b..93ff77a 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp @@ -31,11 +31,12 @@ class MicrosoftNumberingContext : public MangleNumberingContext { llvm::DenseMap<const Type *, unsigned> ManglingNumbers; unsigned LambdaManglingNumber; unsigned StaticLocalNumber; + unsigned StaticThreadlocalNumber; public: MicrosoftNumberingContext() : MangleNumberingContext(), LambdaManglingNumber(0), - StaticLocalNumber(0) {} + StaticLocalNumber(0), StaticThreadlocalNumber(0) {} unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { return ++LambdaManglingNumber; @@ -47,6 +48,8 @@ public: } unsigned getStaticLocalNumber(const VarDecl *VD) override { + if (VD->getTLSKind()) + return ++StaticThreadlocalNumber; return ++StaticLocalNumber; } @@ -63,6 +66,10 @@ public: class MicrosoftCXXABI : public CXXABI { ASTContext &Context; + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor; + llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *> + CtorToDefaultArgExpr; + public: MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } @@ -82,13 +89,36 @@ public: return false; const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - + // In the Microsoft ABI, classes can have one or two vtable pointers. - CharUnits PointerSize = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); + CharUnits PointerSize = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); return Layout.getNonVirtualSize() == PointerSize || Layout.getNonVirtualSize() == PointerSize * 2; - } + } + + void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx, Expr *DAE) override { + CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE; + } + + Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx) override { + return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)]; + } + + const CXXConstructorDecl * + getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { + return RecordToCopyCtor[RD]; + } + + void + addCopyConstructorForExceptionObject(CXXRecordDecl *RD, + CXXConstructorDecl *CD) override { + assert(CD != nullptr); + assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD); + RecordToCopyCtor[RD] = CD; + } MangleNumberingContext *createMangleNumberingContext() const override { return new MicrosoftNumberingContext(); @@ -186,29 +216,28 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) { std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign( const MemberPointerType *MPT) const { - const TargetInfo &Target = Context.getTargetInfo(); - assert(Target.getTriple().getArch() == llvm::Triple::x86 || - Target.getTriple().getArch() == llvm::Triple::x86_64); - unsigned Ptrs, Ints; - std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); // The nominal struct is laid out with pointers followed by ints and aligned // to a pointer width if any are present and an int width otherwise. + const TargetInfo &Target = Context.getTargetInfo(); unsigned PtrSize = Target.getPointerWidth(0); unsigned IntSize = Target.getIntWidth(); + + unsigned Ptrs, Ints; + std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); uint64_t Width = Ptrs * PtrSize + Ints * IntSize; unsigned Align; // When MSVC does x86_32 record layout, it aligns aggregate member pointers to // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for // function memptrs. - if (Ptrs + Ints > 1 && Target.getTriple().getArch() == llvm::Triple::x86) - Align = 8 * 8; + if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit()) + Align = 64; else if (Ptrs) Align = Target.getPointerAlign(0); else Align = Target.getIntAlign(); - if (Target.getTriple().getArch() == llvm::Triple::x86_64) + if (Target.getTriple().isArch64Bit()) Width = llvm::RoundUpToAlignment(Width, Align); return std::make_pair(Width, Align); } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 72f90f6..db5b48e 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -67,11 +67,15 @@ static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { return getEffectiveDeclContext(cast<Decl>(DC)); } -static const FunctionDecl *getStructor(const FunctionDecl *fn) { - if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate()) - return ftd->getTemplatedDecl(); +static const FunctionDecl *getStructor(const NamedDecl *ND) { + if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND)) + return FTD->getTemplatedDecl(); - return fn; + const auto *FD = cast<FunctionDecl>(ND); + if (const auto *FTD = FD->getPrimaryTemplate()) + return FTD->getTemplatedDecl(); + + return FD; } static bool isLambda(const NamedDecl *ND) { @@ -89,6 +93,8 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext { llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator; llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier; llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds; + llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds; + llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds; public: MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) @@ -109,6 +115,16 @@ public: void mangleCXXVBTable(const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath, raw_ostream &Out) override; + void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile, + uint32_t NumEntries, raw_ostream &Out) override; + void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries, + raw_ostream &Out) override; + void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD, + CXXCtorType CT, uint32_t Size, uint32_t NVOffset, + int32_t VBPtrOffset, uint32_t VBIndex, + raw_ostream &Out) override; + void mangleCXXCatchHandlerType(QualType T, uint32_t Flags, + raw_ostream &Out) override; void mangleCXXRTTI(QualType T, raw_ostream &Out) override; void mangleCXXRTTIName(QualType T, raw_ostream &Out) override; void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived, @@ -131,10 +147,18 @@ public: void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber, raw_ostream &) override; void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override; + void mangleThreadSafeStaticGuardVariable(const VarDecl *D, unsigned GuardNum, + raw_ostream &Out) override; void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override; void mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &Out) override; + void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl, + raw_ostream &Out) override; + void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl, + raw_ostream &Out) override; void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override; + void mangleCXXVTableBitSet(const CXXRecordDecl *RD, + raw_ostream &Out) override; bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { // Lambda closure types are already numbered. if (isLambda(ND)) @@ -211,6 +235,12 @@ public: 64) {} MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_, + const CXXConstructorDecl *D, CXXCtorType Type) + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), + PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == + 64) {} + + MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == @@ -220,7 +250,7 @@ public: void mangle(const NamedDecl *D, StringRef Prefix = "\01?"); void mangleName(const NamedDecl *ND); - void mangleFunctionEncoding(const FunctionDecl *FD); + void mangleFunctionEncoding(const FunctionDecl *FD, bool ShouldMangle); void mangleVariableEncoding(const VarDecl *VD); void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD); void mangleMemberFunctionPointer(const CXXRecordDecl *RD, @@ -247,7 +277,7 @@ private: void mangleQualifiers(Qualifiers Quals, bool IsMember); void mangleRefQualifier(RefQualifierKind RefQualifier); void manglePointerCVQualifiers(Qualifiers Quals); - void manglePointerExtQualifiers(Qualifiers Quals, const Type *PointeeType); + void manglePointerExtQualifiers(Qualifiers Quals, QualType PointeeType); void mangleUnscopedTemplateName(const TemplateDecl *ND); void @@ -261,6 +291,7 @@ private: #define ABSTRACT_TYPE(CLASS, PARENT) #define NON_CANONICAL_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \ + Qualifiers Quals, \ SourceRange Range); #include "clang/AST/TypeNodes.def" #undef ABSTRACT_TYPE @@ -271,6 +302,7 @@ private: void mangleDecayedArrayType(const ArrayType *T); void mangleArrayType(const ArrayType *T); void mangleFunctionClass(const FunctionDecl *FD); + void mangleCallingConvention(CallingConv CC); void mangleCallingConvention(const FunctionType *T); void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean); void mangleExpression(const Expr *E); @@ -352,7 +384,7 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { Out << Prefix; mangleName(D); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - mangleFunctionEncoding(FD); + mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD)); else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) mangleVariableEncoding(VD); else { @@ -365,7 +397,8 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { } } -void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { +void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD, + bool ShouldMangle) { // <type-encoding> ::= <function-class> <function-type> // Since MSVC operates on the type as written and not the canonical type, it @@ -380,13 +413,20 @@ void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // extern "C" functions can hold entities that must be mangled. // As it stands, these functions still need to get expressed in the full // external name. They have their class and type omitted, replaced with '9'. - if (Context.shouldMangleDeclName(FD)) { - // First, the function class. + if (ShouldMangle) { + // We would like to mangle all extern "C" functions using this additional + // component but this would break compatibility with MSVC's behavior. + // Instead, do this when we know that compatibility isn't important (in + // other words, when it is an overloaded extern "C" funciton). + if (FD->isExternC() && FD->hasAttr<OverloadableAttr>()) + Out << "$$J0"; + mangleFunctionClass(FD); mangleFunctionType(FT, FD); - } else + } else { Out << '9'; + } } void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { @@ -422,7 +462,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { Ty->isMemberPointerType()) { mangleType(Ty, SR, QMM_Drop); manglePointerExtQualifiers( - Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), nullptr); + Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), QualType()); if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) { mangleQualifiers(MPT->getPointeeType().getQualifiers(), true); // Member pointers are suffixed with a back reference to the member @@ -525,7 +565,7 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, } } else { mangleName(MD); - mangleFunctionEncoding(MD); + mangleFunctionEncoding(MD, /*ShouldMangle=*/true); } } else { // Null single inheritance member functions are encoded as a simple nullptr. @@ -559,7 +599,7 @@ void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk( Out << "$B"; mangleNumber(OffsetInVFTable); Out << 'A'; - Out << (PointersAre64Bit ? 'A' : 'E'); + mangleCallingConvention(MD->getType()->getAs<FunctionProtoType>()); } void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { @@ -757,12 +797,18 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: - if (ND == Structor) { - assert(StructorType == Ctor_Complete && - "Should never be asked to mangle a ctor other than complete"); + if (Structor == getStructor(ND)) { + if (StructorType == Ctor_CopyingClosure) { + Out << "?_O"; + return; + } + if (StructorType == Ctor_DefaultClosure) { + Out << "?_F"; + return; + } } Out << "?0"; - break; + return; case DeclarationName::CXXDestructorName: if (ND == Structor) @@ -1134,10 +1180,13 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, cast<ValueDecl>(ND)); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); - if (MD && MD->isInstance()) + if (MD && MD->isInstance()) { mangleMemberFunctionPointer(MD->getParent()->getMostRecentDecl(), MD); - else - mangle(FD, "$1?"); + } else { + Out << "$1?"; + mangleName(FD); + mangleFunctionEncoding(FD, /*ShouldMangle=*/true); + } } else { mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?"); } @@ -1171,7 +1220,12 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, if (TemplateArgs.empty()) { if (isa<TemplateTypeParmDecl>(Parm) || isa<TemplateTemplateParmDecl>(Parm)) - Out << "$$V"; + // MSVC 2015 changed the mangling for empty expanded template packs, + // use the old mangling for link compatibility for old versions. + Out << (Context.getASTContext().getLangOpts().isCompatibleWithMSVC( + LangOptions::MSVC2015) + ? "$$V" + : "$$$V"); else if (isa<NonTypeTemplateParmDecl>(Parm)) Out << "$S"; else @@ -1298,11 +1352,11 @@ MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) { } } -void -MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals, - const Type *PointeeType) { +void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals, + QualType PointeeType) { bool HasRestrict = Quals.hasRestrict(); - if (PointersAre64Bit && (!PointeeType || !PointeeType->isFunctionType())) + if (PointersAre64Bit && + (PointeeType.isNull() || !PointeeType->isFunctionType())) Out << 'E'; if (HasRestrict) @@ -1338,29 +1392,38 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, // e.g. // void (*x)(void) will not form a backreference with void x(void) void *TypePtr; - if (const DecayedType *DT = T->getAs<DecayedType>()) { - TypePtr = DT->getOriginalType().getCanonicalType().getAsOpaquePtr(); + if (const auto *DT = T->getAs<DecayedType>()) { + QualType OriginalType = DT->getOriginalType(); + // All decayed ArrayTypes should be treated identically; as-if they were + // a decayed IncompleteArrayType. + if (const auto *AT = getASTContext().getAsArrayType(OriginalType)) + OriginalType = getASTContext().getIncompleteArrayType( + AT->getElementType(), AT->getSizeModifier(), + AT->getIndexTypeCVRQualifiers()); + + TypePtr = OriginalType.getCanonicalType().getAsOpaquePtr(); // If the original parameter was textually written as an array, // instead treat the decayed parameter like it's const. // // e.g. // int [] -> int * const - if (DT->getOriginalType()->isArrayType()) + if (OriginalType->isArrayType()) T = T.withConst(); - } else + } else { TypePtr = T.getCanonicalType().getAsOpaquePtr(); + } ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); if (Found == TypeBackReferences.end()) { - size_t OutSizeBefore = Out.GetNumBytesInBuffer(); + size_t OutSizeBefore = Out.tell(); mangleType(T, Range, QMM_Drop); // See if it's worth creating a back reference. // Only types longer than 1 character are considered // and only 10 back references slots are available: - bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1); + bool LongerThanOneChar = (Out.tell() - OutSizeBefore > 1); if (LongerThanOneChar && TypeBackReferences.size() < 10) { size_t Size = TypeBackReferences.size(); TypeBackReferences[TypePtr] = Size; @@ -1388,7 +1451,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, } bool IsPointer = T->isAnyPointerType() || T->isMemberPointerType() || - T->isBlockPointerType(); + T->isReferenceType() || T->isBlockPointerType(); switch (QMM) { case QMM_Drop: @@ -1415,11 +1478,6 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, break; } - // We have to mangle these now, while we still have enough information. - if (IsPointer) { - manglePointerCVQualifiers(Quals); - manglePointerExtQualifiers(Quals, T->getPointeeType().getTypePtr()); - } const Type *ty = T.getTypePtr(); switch (ty->getTypeClass()) { @@ -1430,7 +1488,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, return; #define TYPE(CLASS, PARENT) \ case Type::CLASS: \ - mangleType(cast<CLASS##Type>(ty), Range); \ + mangleType(cast<CLASS##Type>(ty), Quals, Range); \ break; #include "clang/AST/TypeNodes.def" #undef ABSTRACT_TYPE @@ -1439,7 +1497,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, } } -void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, +void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, SourceRange Range) { // <type> ::= <builtin-type> // <builtin-type> ::= X # void @@ -1525,7 +1583,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, } // <type> ::= <function-type> -void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, +void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, Qualifiers, SourceRange) { // Structors only appear in decls, so at this point we know it's not a // structor type. @@ -1539,7 +1597,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, } } void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, - SourceRange) { + Qualifiers, SourceRange) { llvm_unreachable("Can't mangle K&R function prototypes"); } @@ -1553,24 +1611,34 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, SourceRange Range; if (D) Range = D->getSourceRange(); - bool IsStructor = false, HasThisQuals = ForceThisQuals; + bool IsStructor = false, HasThisQuals = ForceThisQuals, IsCtorClosure = false; + CallingConv CC = T->getCallConv(); if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) { if (MD->isInstance()) HasThisQuals = true; - if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) + if (isa<CXXDestructorDecl>(MD)) { IsStructor = true; + } else if (isa<CXXConstructorDecl>(MD)) { + IsStructor = true; + IsCtorClosure = (StructorType == Ctor_CopyingClosure || + StructorType == Ctor_DefaultClosure) && + getStructor(MD) == Structor; + if (IsCtorClosure) + CC = getASTContext().getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true); + } } // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (HasThisQuals) { Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals()); - manglePointerExtQualifiers(Quals, /*PointeeType=*/nullptr); + manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType()); mangleRefQualifier(Proto->getRefQualifier()); mangleQualifiers(Quals, /*IsMember=*/false); } - mangleCallingConvention(T); + mangleCallingConvention(CC); // <return-type> ::= <type> // ::= @ # structors (they have no declared return type) @@ -1584,6 +1652,29 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z"); return; } + if (IsCtorClosure) { + // Default constructor closure and copy constructor closure both return + // void. + Out << 'X'; + + if (StructorType == Ctor_DefaultClosure) { + // Default constructor closure always has no arguments. + Out << 'X'; + } else if (StructorType == Ctor_CopyingClosure) { + // Copy constructor closure always takes an unqualified reference. + mangleArgumentType(getASTContext().getLValueReferenceType( + Proto->getParamType(0) + ->getAs<LValueReferenceType>() + ->getPointeeType(), + /*SpelledAsLValue=*/true), + Range); + Out << '@'; + } else { + llvm_unreachable("unexpected constructor closure!"); + } + Out << 'Z'; + return; + } Out << '@'; } else { QualType ResultType = Proto->getReturnType(); @@ -1608,7 +1699,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, Out << 'X'; } else { // Happens for function pointer type arguments for example. - for (const QualType Arg : Proto->param_types()) + for (const QualType &Arg : Proto->param_types()) mangleArgumentType(Arg, Range); // <builtin-type> ::= Z # ellipsis if (Proto->isVariadic()) @@ -1673,10 +1764,11 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { else Out << 'Q'; } - } else + } else { Out << 'Y'; + } } -void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { +void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { // <calling-convention> ::= A # __cdecl // ::= B # __export __cdecl // ::= C # __pascal @@ -1693,7 +1785,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { // that keyword. (It didn't actually export them, it just made them so // that they could be in a DLL and somebody from another module could call // them.) - CallingConv CC = T->getCallConv(); + switch (CC) { default: llvm_unreachable("Unsupported CC for mangling"); @@ -1707,6 +1799,9 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { case CC_X86VectorCall: Out << 'Q'; break; } } +void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { + mangleCallingConvention(T->getCallConv()); +} void MicrosoftCXXNameMangler::mangleThrowSpecification( const FunctionProtoType *FT) { // <throw-spec> ::= Z # throw(...) (default) @@ -1719,7 +1814,7 @@ void MicrosoftCXXNameMangler::mangleThrowSpecification( } void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T, - SourceRange Range) { + Qualifiers, SourceRange Range) { // Probably should be mangled as a template instantiation; need to see what // VC does first. DiagnosticsEngine &Diags = Context.getDiags(); @@ -1734,10 +1829,12 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T, // <struct-type> ::= U <name> // <class-type> ::= V <name> // <enum-type> ::= W4 <name> -void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) { +void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers, + SourceRange) { mangleType(cast<TagType>(T)->getDecl()); } -void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) { +void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers, + SourceRange) { mangleType(cast<TagType>(T)->getDecl()); } void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { @@ -1772,39 +1869,41 @@ void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) { manglePointerCVQualifiers(T->getElementType().getQualifiers()); mangleType(T->getElementType(), SourceRange()); } -void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, +void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, Qualifiers, SourceRange) { llvm_unreachable("Should have been special cased"); } -void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T, +void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T, Qualifiers, SourceRange) { llvm_unreachable("Should have been special cased"); } void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T, - SourceRange) { + Qualifiers, SourceRange) { llvm_unreachable("Should have been special cased"); } void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T, - SourceRange) { + Qualifiers, SourceRange) { llvm_unreachable("Should have been special cased"); } void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { QualType ElementTy(T, 0); SmallVector<llvm::APInt, 3> Dimensions; for (;;) { - if (const ConstantArrayType *CAT = - getASTContext().getAsConstantArrayType(ElementTy)) { + if (ElementTy->isConstantArrayType()) { + const ConstantArrayType *CAT = + getASTContext().getAsConstantArrayType(ElementTy); Dimensions.push_back(CAT->getSize()); ElementTy = CAT->getElementType(); + } else if (ElementTy->isIncompleteArrayType()) { + const IncompleteArrayType *IAT = + getASTContext().getAsIncompleteArrayType(ElementTy); + Dimensions.push_back(llvm::APInt(32, 0)); + ElementTy = IAT->getElementType(); } else if (ElementTy->isVariableArrayType()) { const VariableArrayType *VAT = getASTContext().getAsVariableArrayType(ElementTy); - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this variable-length array yet"); - Diags.Report(VAT->getSizeExpr()->getExprLoc(), DiagID) - << VAT->getBracketsRange(); - return; + Dimensions.push_back(llvm::APInt(32, 0)); + ElementTy = VAT->getElementType(); } else if (ElementTy->isDependentSizedArrayType()) { // The dependent expression has to be folded into a constant (TODO). const DependentSizedArrayType *DSAT = @@ -1815,12 +1914,9 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID) << DSAT->getBracketsRange(); return; - } else if (const IncompleteArrayType *IAT = - getASTContext().getAsIncompleteArrayType(ElementTy)) { - Dimensions.push_back(llvm::APInt(32, 0)); - ElementTy = IAT->getElementType(); + } else { + break; } - else break; } Out << 'Y'; // <dimension-count> ::= <number> # number of extra dimensions @@ -1833,9 +1929,11 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { // <type> ::= <pointer-to-member-type> // <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> // <class name> <type> -void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, +void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, Qualifiers Quals, SourceRange Range) { QualType PointeeType = T->getPointeeType(); + manglePointerCVQualifiers(Quals); + manglePointerExtQualifiers(Quals, PointeeType); if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) { Out << '8'; mangleName(T->getClass()->castAs<RecordType>()->getDecl()); @@ -1848,7 +1946,7 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, } void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T, - SourceRange Range) { + Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this template type parameter type yet"); @@ -1856,9 +1954,8 @@ void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T, << Range; } -void MicrosoftCXXNameMangler::mangleType( - const SubstTemplateTypeParmPackType *T, - SourceRange Range) { +void MicrosoftCXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T, + Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this substituted parameter pack yet"); @@ -1869,40 +1966,46 @@ void MicrosoftCXXNameMangler::mangleType( // <type> ::= <pointer-type> // <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type> // # the E is required for 64-bit non-static pointers -void MicrosoftCXXNameMangler::mangleType(const PointerType *T, +void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals, SourceRange Range) { - QualType PointeeTy = T->getPointeeType(); - mangleType(PointeeTy, Range); + QualType PointeeType = T->getPointeeType(); + manglePointerCVQualifiers(Quals); + manglePointerExtQualifiers(Quals, PointeeType); + mangleType(PointeeType, Range); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, - SourceRange Range) { + Qualifiers Quals, SourceRange Range) { + QualType PointeeType = T->getPointeeType(); + manglePointerCVQualifiers(Quals); + manglePointerExtQualifiers(Quals, PointeeType); // Object pointers never have qualifiers. Out << 'A'; - manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); - mangleType(T->getPointeeType(), Range); + mangleType(PointeeType, Range); } // <type> ::= <reference-type> // <reference-type> ::= A E? <cvr-qualifiers> <type> // # the E is required for 64-bit non-static lvalue references void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, - SourceRange Range) { - Out << 'A'; - manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); - mangleType(T->getPointeeType(), Range); + Qualifiers Quals, SourceRange Range) { + QualType PointeeType = T->getPointeeType(); + Out << (Quals.hasVolatile() ? 'B' : 'A'); + manglePointerExtQualifiers(Quals, PointeeType); + mangleType(PointeeType, Range); } // <type> ::= <r-value-reference-type> // <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type> // # the E is required for 64-bit non-static rvalue references void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T, - SourceRange Range) { - Out << "$$Q"; - manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); - mangleType(T->getPointeeType(), Range); + Qualifiers Quals, SourceRange Range) { + QualType PointeeType = T->getPointeeType(); + Out << (Quals.hasVolatile() ? "$$R" : "$$Q"); + manglePointerExtQualifiers(Quals, PointeeType); + mangleType(PointeeType, Range); } -void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, +void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -1911,41 +2014,47 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, << Range; } -void MicrosoftCXXNameMangler::mangleType(const VectorType *T, +void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals, SourceRange Range) { const BuiltinType *ET = T->getElementType()->getAs<BuiltinType>(); assert(ET && "vectors with non-builtin elements are unsupported"); uint64_t Width = getASTContext().getTypeSize(T); // Pattern match exactly the typedefs in our intrinsic headers. Anything that // doesn't match the Intel types uses a custom mangling below. - bool IntelVector = true; - if (Width == 64 && ET->getKind() == BuiltinType::LongLong) { - Out << "T__m64"; - } else if (Width == 128 || Width == 256) { - if (ET->getKind() == BuiltinType::Float) - Out << "T__m" << Width; - else if (ET->getKind() == BuiltinType::LongLong) - Out << "T__m" << Width << 'i'; - else if (ET->getKind() == BuiltinType::Double) - Out << "U__m" << Width << 'd'; - else - IntelVector = false; + bool IsBuiltin = true; + llvm::Triple::ArchType AT = + getASTContext().getTargetInfo().getTriple().getArch(); + if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) { + if (Width == 64 && ET->getKind() == BuiltinType::LongLong) { + Out << "T__m64"; + } else if (Width >= 128) { + if (ET->getKind() == BuiltinType::Float) + Out << "T__m" << Width; + else if (ET->getKind() == BuiltinType::LongLong) + Out << "T__m" << Width << 'i'; + else if (ET->getKind() == BuiltinType::Double) + Out << "U__m" << Width << 'd'; + else + IsBuiltin = false; + } else { + IsBuiltin = false; + } } else { - IntelVector = false; + IsBuiltin = false; } - if (!IntelVector) { + if (!IsBuiltin) { // The MS ABI doesn't have a special mangling for vector types, so we define // our own mangling to handle uses of __vector_size__ on user-specified // types, and for extensions like __v4sf. Out << "T__clang_vec" << T->getNumElements() << '_'; - mangleType(ET, Range); + mangleType(ET, Quals, Range); } Out << "@@"; } -void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, +void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -1954,7 +2063,7 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, << Range; } void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, - SourceRange Range) { + Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this dependent-sized extended vector type yet"); @@ -1962,14 +2071,14 @@ void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, << Range; } -void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, +void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, SourceRange) { // ObjC interfaces have structs underlying them. Out << 'U'; mangleName(T->getDecl()); } -void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, +void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers, SourceRange Range) { // We don't allow overloading by different protocol qualification, // so mangling them isn't necessary. @@ -1977,20 +2086,23 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, } void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T, - SourceRange Range) { + Qualifiers Quals, SourceRange Range) { + QualType PointeeType = T->getPointeeType(); + manglePointerCVQualifiers(Quals); + manglePointerExtQualifiers(Quals, PointeeType); + Out << "_E"; - QualType pointee = T->getPointeeType(); - mangleFunctionType(pointee->castAs<FunctionProtoType>()); + mangleFunctionType(PointeeType->castAs<FunctionProtoType>()); } void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *, - SourceRange) { + Qualifiers, SourceRange) { llvm_unreachable("Cannot mangle injected class name type."); } void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T, - SourceRange Range) { + Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this template specialization type yet"); @@ -1998,7 +2110,7 @@ void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T, << Range; } -void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T, +void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -2008,8 +2120,8 @@ void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T, } void MicrosoftCXXNameMangler::mangleType( - const DependentTemplateSpecializationType *T, - SourceRange Range) { + const DependentTemplateSpecializationType *T, Qualifiers, + SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this dependent template specialization type yet"); @@ -2017,7 +2129,7 @@ void MicrosoftCXXNameMangler::mangleType( << Range; } -void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T, +void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -2026,7 +2138,7 @@ void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T, << Range; } -void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T, +void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -2035,7 +2147,7 @@ void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T, << Range; } -void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T, +void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -2044,7 +2156,7 @@ void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T, << Range; } -void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T, +void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -2054,7 +2166,7 @@ void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T, } void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T, - SourceRange Range) { + Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this unary transform type yet"); @@ -2062,7 +2174,8 @@ void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T, << Range; } -void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) { +void MicrosoftCXXNameMangler::mangleType(const AutoType *T, Qualifiers, + SourceRange Range) { assert(T->getDeducedType().isNull() && "expecting a dependent type!"); DiagnosticsEngine &Diags = Context.getDiags(); @@ -2072,7 +2185,7 @@ void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) { << Range; } -void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, +void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -2273,6 +2386,74 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); } +void MicrosoftMangleContextImpl::mangleCXXCatchHandlerType(QualType T, + uint32_t Flags, + raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "llvm.eh.handlertype."; + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); + Mangler.getStream() << '.' << Flags; +} + +void MicrosoftMangleContextImpl::mangleCXXThrowInfo(QualType T, + bool IsConst, + bool IsVolatile, + uint32_t NumEntries, + raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "_TI"; + if (IsConst) + Mangler.getStream() << 'C'; + if (IsVolatile) + Mangler.getStream() << 'V'; + Mangler.getStream() << NumEntries; + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); +} + +void MicrosoftMangleContextImpl::mangleCXXCatchableTypeArray( + QualType T, uint32_t NumEntries, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "_CTA"; + Mangler.getStream() << NumEntries; + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); +} + +void MicrosoftMangleContextImpl::mangleCXXCatchableType( + QualType T, const CXXConstructorDecl *CD, CXXCtorType CT, uint32_t Size, + uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBIndex, + raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "_CT"; + + llvm::SmallString<64> RTTIMangling; + { + llvm::raw_svector_ostream Stream(RTTIMangling); + mangleCXXRTTI(T, Stream); + } + Mangler.getStream() << RTTIMangling.substr(1); + + // VS2015 CTP6 omits the copy-constructor in the mangled name. This name is, + // in fact, superfluous but I'm not sure the change was made consciously. + // TODO: Revisit this when VS2015 gets released. + llvm::SmallString<64> CopyCtorMangling; + if (CD) { + llvm::raw_svector_ostream Stream(CopyCtorMangling); + mangleCXXCtor(CD, CT, Stream); + } + Mangler.getStream() << CopyCtorMangling.substr(1); + + Mangler.getStream() << Size; + if (VBPtrOffset == -1) { + if (NVOffset) { + Mangler.getStream() << NVOffset; + } + } else { + Mangler.getStream() << NVOffset; + Mangler.getStream() << VBPtrOffset; + Mangler.getStream() << VBIndex; + } +} + void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor( const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) { @@ -2318,6 +2499,28 @@ void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator( Mangler.getStream() << '@'; } +void MicrosoftMangleContextImpl::mangleSEHFilterExpression( + const NamedDecl *EnclosingDecl, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + // The function body is in the same comdat as the function with the handler, + // so the numbering here doesn't have to be the same across TUs. + // + // <mangled-name> ::= ?filt$ <filter-number> @0 + Mangler.getStream() << "\01?filt$" << SEHFilterIds[EnclosingDecl]++ << "@0@"; + Mangler.mangleName(EnclosingDecl); +} + +void MicrosoftMangleContextImpl::mangleSEHFinallyBlock( + const NamedDecl *EnclosingDecl, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + // The function body is in the same comdat as the function with the handler, + // so the numbering here doesn't have to be the same across TUs. + // + // <mangled-name> ::= ?fin$ <filter-number> @0 + Mangler.getStream() << "\01?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@"; + Mangler.mangleName(EnclosingDecl); +} + void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) { // This is just a made up unique string for the purposes of tbaa. undname // does *not* know how to demangle it. @@ -2329,7 +2532,7 @@ void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) { void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, raw_ostream &Out) { - MicrosoftCXXNameMangler mangler(*this, Out); + MicrosoftCXXNameMangler mangler(*this, Out, D, Type); mangler.mangle(D); } @@ -2348,18 +2551,18 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD, getDiags().Report(VD->getLocation(), DiagID); } +void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable( + const VarDecl *VD, unsigned GuardNum, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + + Mangler.getStream() << "\01?$TSS" << GuardNum << '@'; + Mangler.mangleNestedName(VD); +} + void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, raw_ostream &Out) { - // 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 - // mangling, they all get $TSS <number>. - // - // N.B. This means that they can get more than 32 static variable guards in a - // scope. It also means that they broke compatibility with their own ABI. - // <guard-name> ::= ?_B <postfix> @5 <scope-depth> + // ::= ?__J <postfix> @5 <scope-depth> // ::= ?$S <guard-num> @ <postfix> @4IA // The first mangling is what MSVC uses to guard static locals in inline @@ -2371,8 +2574,11 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, MicrosoftCXXNameMangler Mangler(*this, Out); bool Visible = VD->isExternallyVisible(); - // <operator-name> ::= ?_B # local static guard - Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@"); + if (Visible) { + Mangler.getStream() << (VD->getTLSKind() ? "\01??__J" : "\01??_B"); + } else { + Mangler.getStream() << "\01?$S1@"; + } unsigned ScopeDepth = 0; if (Visible && !getNextDiscriminator(VD, ScopeDepth)) // If we do not have a discriminator and are emitting a guard variable for @@ -2553,6 +2759,11 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, Mangler.getStream() << '@'; } +void MicrosoftMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD, + raw_ostream &Out) { + llvm::report_fatal_error("Cannot mangle bitsets yet"); +} + MicrosoftMangleContext * MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { return new MicrosoftMangleContextImpl(Context, Diags); diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp index 3dc750a..2749100 100644 --- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp @@ -27,7 +27,10 @@ IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const { "NSMutableArray", "NSDictionary", "NSMutableDictionary", - "NSNumber" + "NSNumber", + "NSMutableSet", + "NSCountedSet", + "NSMutableOrderedSet" }; if (!ClassIds[K]) @@ -124,6 +127,25 @@ Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { Sel = Ctx.Selectors.getSelector(2, KeyIdents); break; } + case NSMutableArr_addObject: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject")); + break; + case NSMutableArr_insertObjectAtIndex: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("insertObject"), + &Ctx.Idents.get("atIndex") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSMutableArr_setObjectAtIndexedSubscript: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("setObject"), + &Ctx.Idents.get("atIndexedSubscript") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } } return (NSArraySelectors[MK] = Sel); } @@ -209,6 +231,22 @@ Selector NSAPI::getNSDictionarySelector( Sel = Ctx.Selectors.getSelector(2, KeyIdents); break; } + case NSMutableDict_setObjectForKeyedSubscript: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("setObject"), + &Ctx.Idents.get("forKeyedSubscript") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSMutableDict_setValueForKey: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("setValue"), + &Ctx.Idents.get("forKey") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } } return (NSDictionarySelectors[MK] = Sel); } @@ -227,6 +265,63 @@ NSAPI::getNSDictionaryMethodKind(Selector Sel) { return None; } +Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const { + if (NSSetSelectors[MK].isNull()) { + Selector Sel; + switch (MK) { + case NSMutableSet_addObject: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject")); + break; + case NSOrderedSet_insertObjectAtIndex: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("insertObject"), + &Ctx.Idents.get("atIndex") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSOrderedSet_setObjectAtIndex: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("setObject"), + &Ctx.Idents.get("atIndex") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSOrderedSet_setObjectAtIndexedSubscript: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("setObject"), + &Ctx.Idents.get("atIndexedSubscript") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSOrderedSet_replaceObjectAtIndexWithObject: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("replaceObjectAtIndex"), + &Ctx.Idents.get("withObject") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + } + return (NSSetSelectors[MK] = Sel); + } + + return NSSetSelectors[MK]; +} + +Optional<NSAPI::NSSetMethodKind> +NSAPI::getNSSetMethodKind(Selector Sel) { + for (unsigned i = 0; i != NumNSSetMethods; ++i) { + NSSetMethodKind MK = NSSetMethodKind(i); + if (Sel == getNSSetSelector(MK)) + return MK; + } + + return None; +} + Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, bool Instance) const { static const char *ClassSelectorName[NumNSNumberLiteralMethods] = { @@ -410,6 +505,11 @@ StringRef NSAPI::GetNSIntegralKind(QualType T) const { return StringRef(); } +bool NSAPI::isMacroDefined(StringRef Id) const { + // FIXME: Check whether the relevant module macros are visible. + return Ctx.Idents.get(Id).hasMacroDefinition(); +} + bool NSAPI::isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const { if (!Ctx.getLangOpts().ObjC1) diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index 0d070a4..2101a55 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -55,6 +55,52 @@ struct BaseSubobjectInfo { const BaseSubobjectInfo *Derived; }; +/// \brief Externally provided layout. Typically used when the AST source, such +/// as DWARF, lacks all the information that was available at compile time, such +/// as alignment attributes on fields and pragmas in effect. +struct ExternalLayout { + ExternalLayout() : Size(0), Align(0) {} + + /// \brief Overall record size in bits. + uint64_t Size; + + /// \brief Overall record alignment in bits. + uint64_t Align; + + /// \brief Record field offsets in bits. + llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets; + + /// \brief Direct, non-virtual base offsets. + llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets; + + /// \brief Virtual base offsets. + llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets; + + /// Get the offset of the given field. The external source must provide + /// entries for all fields in the record. + uint64_t getExternalFieldOffset(const FieldDecl *FD) { + assert(FieldOffsets.count(FD) && + "Field does not have an external offset"); + return FieldOffsets[FD]; + } + + bool getExternalNVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) { + auto Known = BaseOffsets.find(RD); + if (Known == BaseOffsets.end()) + return false; + BaseOffset = Known->second; + return true; + } + + bool getExternalVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) { + auto Known = VirtualBaseOffsets.find(RD); + if (Known == VirtualBaseOffsets.end()) + return false; + BaseOffset = Known->second; + return true; + } +}; + /// EmptySubobjectMap - Keeps track of which empty subobjects exist at different /// offsets while laying out a C++ class. class EmptySubobjectMap { @@ -541,7 +587,7 @@ protected: /// \brief Whether the external AST source has provided a layout for this /// record. - unsigned ExternalLayout : 1; + unsigned UseExternalLayout : 1; /// \brief Whether we need to infer alignment, even when we have an /// externally-provided layout. @@ -607,26 +653,14 @@ protected: /// avoid visiting virtual bases more than once. llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases; - /// \brief Externally-provided size. - uint64_t ExternalSize; - - /// \brief Externally-provided alignment. - uint64_t ExternalAlign; - - /// \brief Externally-provided field offsets. - llvm::DenseMap<const FieldDecl *, uint64_t> ExternalFieldOffsets; - - /// \brief Externally-provided direct, non-virtual base offsets. - llvm::DenseMap<const CXXRecordDecl *, CharUnits> ExternalBaseOffsets; - - /// \brief Externally-provided virtual base offsets. - llvm::DenseMap<const CXXRecordDecl *, CharUnits> ExternalVirtualBaseOffsets; + /// Valid if UseExternalLayout is true. + ExternalLayout External; RecordLayoutBuilder(const ASTContext &Context, EmptySubobjectMap *EmptySubobjects) : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()), - ExternalLayout(false), InferAlignment(false), + UseExternalLayout(false), InferAlignment(false), Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false), UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0), MaxFieldAlignment(CharUnits::Zero()), @@ -748,8 +782,8 @@ protected: void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); } void setDataSize(uint64_t NewSize) { DataSize = NewSize; } - RecordLayoutBuilder(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION; - void operator=(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION; + RecordLayoutBuilder(const RecordLayoutBuilder &) = delete; + void operator=(const RecordLayoutBuilder &) = delete; }; } // end anonymous namespace @@ -1134,21 +1168,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { // Query the external layout to see if it provides an offset. bool HasExternalLayout = false; - if (ExternalLayout) { + if (UseExternalLayout) { llvm::DenseMap<const CXXRecordDecl *, CharUnits>::iterator Known; - if (Base->IsVirtual) { - Known = ExternalVirtualBaseOffsets.find(Base->Class); - if (Known != ExternalVirtualBaseOffsets.end()) { - Offset = Known->second; - HasExternalLayout = true; - } - } else { - Known = ExternalBaseOffsets.find(Base->Class); - if (Known != ExternalBaseOffsets.end()) { - Offset = Known->second; - HasExternalLayout = true; - } - } + if (Base->IsVirtual) + HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset); + else + HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset); } CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlignment(); @@ -1235,18 +1260,15 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) { // If there is an external AST source, ask it for the various offsets. if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) - if (ExternalASTSource *External = Context.getExternalSource()) { - ExternalLayout = External->layoutRecordType(RD, - ExternalSize, - ExternalAlign, - ExternalFieldOffsets, - ExternalBaseOffsets, - ExternalVirtualBaseOffsets); - + if (ExternalASTSource *Source = Context.getExternalSource()) { + UseExternalLayout = Source->layoutRecordType( + RD, External.Size, External.Align, External.FieldOffsets, + External.BaseOffsets, External.VirtualBaseOffsets); + // Update based on external alignment. - if (ExternalLayout) { - if (ExternalAlign > 0) { - Alignment = Context.toCharUnitsFromBits(ExternalAlign); + if (UseExternalLayout) { + if (External.Align > 0) { + Alignment = Context.toCharUnitsFromBits(External.Align); } else { // The external source didn't have alignment information; infer it. InferAlignment = true; @@ -1588,7 +1610,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // If we're using external layout, give the external layout a chance // to override this information. - if (ExternalLayout) + if (UseExternalLayout) FieldOffset = updateExternalFieldOffset(D, FieldOffset); // Okay, place the bitfield at the calculated offset. @@ -1604,7 +1626,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { FieldAlign = UnpackedFieldAlign = 1; // Diagnose differences in layout due to padding or packing. - if (!ExternalLayout) + if (!UseExternalLayout) CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset, UnpackedFieldAlign, FieldPacked, D); @@ -1727,7 +1749,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D, UnpackedFieldOffset = UnpackedFieldOffset.RoundUpToAlignment(UnpackedFieldAlign); - if (ExternalLayout) { + if (UseExternalLayout) { FieldOffset = Context.toCharUnitsFromBits( updateExternalFieldOffset(D, Context.toBits(FieldOffset))); @@ -1750,7 +1772,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D, // Place this field at the current location. FieldOffsets.push_back(Context.toBits(FieldOffset)); - if (!ExternalLayout) + if (!UseExternalLayout) CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset, Context.toBits(UnpackedFieldOffset), Context.toBits(UnpackedFieldAlign), FieldPacked, D); @@ -1802,15 +1824,15 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { uint64_t RoundedSize = llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment)); - if (ExternalLayout) { + if (UseExternalLayout) { // If we're inferring alignment, and the external size is smaller than // our size after we've rounded up to alignment, conservatively set the // alignment to 1. - if (InferAlignment && ExternalSize < RoundedSize) { + if (InferAlignment && External.Size < RoundedSize) { Alignment = CharUnits::One(); InferAlignment = false; } - setSize(ExternalSize); + setSize(External.Size); return; } @@ -1846,18 +1868,18 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) { // The alignment is not modified when using 'mac68k' alignment or when // we have an externally-supplied layout that also provides overall alignment. - if (IsMac68kAlign || (ExternalLayout && !InferAlignment)) + if (IsMac68kAlign || (UseExternalLayout && !InferAlignment)) return; if (NewAlignment > Alignment) { - assert(llvm::isPowerOf2_32(NewAlignment.getQuantity() && - "Alignment not a power of 2")); + assert(llvm::isPowerOf2_64(NewAlignment.getQuantity()) && + "Alignment not a power of 2"); Alignment = NewAlignment; } if (UnpackedNewAlignment > UnpackedAlignment) { - assert(llvm::isPowerOf2_32(UnpackedNewAlignment.getQuantity() && - "Alignment not a power of 2")); + assert(llvm::isPowerOf2_64(UnpackedNewAlignment.getQuantity()) && + "Alignment not a power of 2"); UnpackedAlignment = UnpackedNewAlignment; } } @@ -1865,11 +1887,8 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment, uint64_t RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field, uint64_t ComputedOffset) { - assert(ExternalFieldOffsets.find(Field) != ExternalFieldOffsets.end() && - "Field does not have an external offset"); - - uint64_t ExternalFieldOffset = ExternalFieldOffsets[Field]; - + uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field); + if (InferAlignment && ExternalFieldOffset < ComputedOffset) { // The externally-supplied field offset is before the field offset we // computed. Assume that the structure is packed. @@ -2152,9 +2171,8 @@ struct MicrosoftRecordLayoutBuilder { typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {} private: - MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) - LLVM_DELETED_FUNCTION; - void operator=(const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION; + MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete; + void operator=(const MicrosoftRecordLayoutBuilder &) = delete; public: void layout(const RecordDecl *RD); void cxxLayout(const CXXRecordDecl *RD); @@ -2252,6 +2270,13 @@ public: /// \brief True if this class is zero sized or first base is zero sized or /// has this property. Only used for MS-ABI. bool LeadsWithZeroSizedBase : 1; + + /// \brief True if the external AST source provided a layout for this record. + bool UseExternalLayout : 1; + + /// \brief The layout provided by the external AST source. Only active if + /// UseExternalLayout is true. + ExternalLayout External; }; } // namespace @@ -2354,8 +2379,9 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) { // In 64-bit mode we always perform an alignment step after laying out vbases. // In 32-bit mode we do not. The check to see if we need to perform alignment // checks the RequiredAlignment field and performs alignment if it isn't 0. - RequiredAlignment = Context.getTargetInfo().getPointerWidth(0) == 64 ? - CharUnits::One() : CharUnits::Zero(); + RequiredAlignment = Context.getTargetInfo().getTriple().isArch64Bit() + ? CharUnits::One() + : CharUnits::Zero(); // Compute the maximum field alignment. MaxFieldAlignment = CharUnits::Zero(); // Honor the default struct packing maximum alignment flag. @@ -2371,6 +2397,13 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) { // Packed attribute forces max field alignment to be 1. if (RD->hasAttr<PackedAttr>()) MaxFieldAlignment = CharUnits::One(); + + // Try to respect the external layout if present. + UseExternalLayout = false; + if (ExternalASTSource *Source = Context.getExternalSource()) + UseExternalLayout = Source->layoutRecordType( + RD, External.Size, External.Align, External.FieldOffsets, + External.BaseOffsets, External.VirtualBaseOffsets); } void @@ -2385,7 +2418,8 @@ MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) { // injection. PointerInfo.Size = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); - PointerInfo.Alignment = PointerInfo.Size; + PointerInfo.Alignment = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0)); // Respect pragma pack. if (!MaxFieldAlignment.isZero()) PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment); @@ -2475,7 +2509,18 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( BaseLayout.leadsWithZeroSizedBase()) Size++; ElementInfo Info = getAdjustedElementInfo(BaseLayout); - CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment); + CharUnits BaseOffset; + + // Respect the external AST source base offset, if present. + bool FoundBase = false; + if (UseExternalLayout) { + FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset); + if (FoundBase) + assert(BaseOffset >= Size && "base offset already allocated"); + } + + if (!FoundBase) + BaseOffset = Size.RoundUpToAlignment(Info.Alignment); Bases.insert(std::make_pair(BaseDecl, BaseOffset)); Size = BaseOffset + BaseLayout.getNonVirtualSize(); PreviousBaseLayout = &BaseLayout; @@ -2499,7 +2544,14 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { placeFieldAtOffset(CharUnits::Zero()); Size = std::max(Size, Info.Size); } else { - CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment); + CharUnits FieldOffset; + if (UseExternalLayout) { + FieldOffset = + Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD)); + assert(FieldOffset >= Size && "field offset already allocated"); + } else { + FieldOffset = Size.RoundUpToAlignment(Info.Alignment); + } placeFieldAtOffset(FieldOffset); Size = FieldOffset + Info.Size; } @@ -2573,14 +2625,16 @@ void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) { CharUnits InjectionSite = VBPtrOffset; // But before we do, make sure it's properly aligned. VBPtrOffset = VBPtrOffset.RoundUpToAlignment(PointerInfo.Alignment); + // Shift everything after the vbptr down, unless we're using an external + // layout. + if (UseExternalLayout) + return; // Determine where the first field should be laid out after the vbptr. CharUnits FieldStart = VBPtrOffset + PointerInfo.Size; // Make sure that the amount we push the fields back by is a multiple of the // alignment. CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment( std::max(RequiredAlignment, Alignment)); - // Increase the size of the object and push back all fields by the offset - // amount. Size += Offset; for (uint64_t &FieldOffset : FieldOffsets) FieldOffset += Context.toBits(Offset); @@ -2647,7 +2701,18 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { } // Insert the virtual base. ElementInfo Info = getAdjustedElementInfo(BaseLayout); - CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment); + CharUnits BaseOffset; + + // Respect the external AST source base offset, if present. + bool FoundBase = false; + if (UseExternalLayout) { + FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset); + if (FoundBase) + assert(BaseOffset >= Size && "base offset already allocated"); + } + if (!FoundBase) + BaseOffset = Size.RoundUpToAlignment(Info.Alignment); + VBases.insert(std::make_pair(BaseDecl, ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp))); Size = BaseOffset + BaseLayout.getNonVirtualSize(); @@ -2677,6 +2742,12 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) { else Size = MinEmptyStructSize; } + + if (UseExternalLayout) { + Size = Context.toCharUnitsFromBits(External.Size); + if (External.Align) + Alignment = Context.toCharUnitsFromBits(External.Align); + } } // Recursively walks the non-virtual bases of a class and determines if any of @@ -2815,7 +2886,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; - if (isMsLayout(D) && !D->getASTContext().getExternalSource()) { + if (isMsLayout(D)) { NewEntry = BuildMicrosoftASTRecordLayout(D); } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { EmptySubobjectMap EmptySubobjects(*this, RD); @@ -2905,11 +2976,11 @@ void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) { // Look up the cache entry. Since we're working with the first // declaration, its parent must be the class definition, which is // the correct key for the KeyFunctions hash. - llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr>::iterator - I = KeyFunctions.find(Method->getParent()); + const auto &Map = KeyFunctions; + auto I = Map.find(Method->getParent()); // If it's not cached, there's nothing to do. - if (I == KeyFunctions.end()) return; + if (I == Map.end()) return; // If it is cached, check whether it's the target method, and if so, // remove it from the cache. Note, the call to 'get' might invalidate diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index 68c7e72..09bb17b 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -95,10 +95,16 @@ void Stmt::EnableStatistics() { Stmt *Stmt::IgnoreImplicit() { Stmt *s = this; - if (ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(s)) + if (auto *ewc = dyn_cast<ExprWithCleanups>(s)) s = ewc->getSubExpr(); - while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(s)) + if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s)) + s = mte->GetTemporaryExpr(); + + if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s)) + s = bte->getSubExpr(); + + while (auto *ice = dyn_cast<ImplicitCastExpr>(s)) s = ice->getSubExpr(); return s; @@ -586,7 +592,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, SourceLocation EndLoc = getAsmString()->getLocationOfByte(CurPtr - StrStart, SM, LO, TI); - Pieces.push_back(AsmStringPiece(N, Str, BeginLoc, EndLoc)); + Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); continue; } @@ -620,7 +626,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, SourceLocation EndLoc = getAsmString()->getLocationOfByte(NameEnd + 1 - StrStart, SM, LO, TI); - Pieces.push_back(AsmStringPiece(N, Str, BeginLoc, EndLoc)); + Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); CurPtr = NameEnd+1; continue; @@ -934,8 +940,7 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { } SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond) - : Stmt(SwitchStmtClass), FirstCase(nullptr), AllEnumCasesCovered(0) -{ + : Stmt(SwitchStmtClass), FirstCase(nullptr, false) { setConditionVariable(C, Var); SubExprs[COND] = cond; SubExprs[BODY] = nullptr; @@ -1241,17 +1246,47 @@ OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPFirstprivateClause(N); } -OMPLastprivateClause *OMPLastprivateClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { +void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) { + assert(PrivateCopies.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end()); +} + +void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { + assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " + "not the same as the " + "preallocated buffer"); + std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end()); +} + +void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { + assert(DstExprs.size() == varlist_size() && "Number of destination " + "expressions is not the same as " + "the preallocated buffer"); + std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); +} + +void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { + assert(AssignmentOps.size() == varlist_size() && + "Number of assignment expressions is not the same as the preallocated " + "buffer"); + std::copy(AssignmentOps.begin(), AssignmentOps.end(), + getDestinationExprs().end()); +} + +OMPLastprivateClause *OMPLastprivateClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); + 5 * sizeof(Expr *) * VL.size()); OMPLastprivateClause *Clause = new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setSourceExprs(SrcExprs); + Clause->setDestinationExprs(DstExprs); + Clause->setAssignmentOps(AssignmentOps); return Clause; } @@ -1259,7 +1294,7 @@ OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); + 5 * sizeof(Expr *) * N); return new (Mem) OMPLastprivateClause(N); } @@ -1285,27 +1320,56 @@ OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPSharedClause(N); } -OMPLinearClause *OMPLinearClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ColonLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL, Expr *Step) { +void OMPLinearClause::setInits(ArrayRef<Expr *> IL) { + assert(IL.size() == varlist_size() && + "Number of inits is not the same as the preallocated buffer"); + std::copy(IL.begin(), IL.end(), varlist_end()); +} + +void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) { + assert(UL.size() == varlist_size() && + "Number of updates is not the same as the preallocated buffer"); + std::copy(UL.begin(), UL.end(), getInits().end()); +} + +void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) { + assert(FL.size() == varlist_size() && + "Number of final updates is not the same as the preallocated buffer"); + std::copy(FL.begin(), FL.end(), getUpdates().end()); +} + +OMPLinearClause * +OMPLinearClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, + ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) { + // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions + // (Step and CalcStep). void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * (VL.size() + 1)); + (4 * VL.size() + 2) * sizeof(Expr *)); OMPLinearClause *Clause = new (Mem) OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setInits(IL); + // Fill update and final expressions with zeroes, they are provided later, + // after the directive construction. + std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(), + nullptr); + std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(), + nullptr); Clause->setStep(Step); + Clause->setCalcStep(CalcStep); return Clause; } OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C, unsigned NumVars) { + // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions + // (Step and CalcStep). void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * (NumVars + 1)); + (4 * NumVars + 2) * sizeof(Expr *)); return new (Mem) OMPLinearClause(NumVars); } @@ -1331,17 +1395,41 @@ OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPAlignedClause(NumVars); } -OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { +void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { + assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " + "not the same as the " + "preallocated buffer"); + std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); +} + +void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { + assert(DstExprs.size() == varlist_size() && "Number of destination " + "expressions is not the same as " + "the preallocated buffer"); + std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); +} + +void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { + assert(AssignmentOps.size() == varlist_size() && + "Number of assignment expressions is not the same as the preallocated " + "buffer"); + std::copy(AssignmentOps.begin(), AssignmentOps.end(), + getDestinationExprs().end()); +} + +OMPCopyinClause *OMPCopyinClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); + 4 * sizeof(Expr *) * VL.size()); OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setSourceExprs(SrcExprs); + Clause->setDestinationExprs(DstExprs); + Clause->setAssignmentOps(AssignmentOps); return Clause; } @@ -1349,21 +1437,45 @@ OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); + 4 * sizeof(Expr *) * N); return new (Mem) OMPCopyinClause(N); } -OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { +void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { + assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " + "not the same as the " + "preallocated buffer"); + std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); +} + +void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { + assert(DstExprs.size() == varlist_size() && "Number of destination " + "expressions is not the same as " + "the preallocated buffer"); + std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); +} + +void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { + assert(AssignmentOps.size() == varlist_size() && + "Number of assignment expressions is not the same as the preallocated " + "buffer"); + std::copy(AssignmentOps.begin(), AssignmentOps.end(), + getDestinationExprs().end()); +} + +OMPCopyprivateClause *OMPCopyprivateClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); + 4 * sizeof(Expr *) * VL.size()); OMPCopyprivateClause *Clause = new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setSourceExprs(SrcExprs); + Clause->setDestinationExprs(DstExprs); + Clause->setAssignmentOps(AssignmentOps); return Clause; } @@ -1371,7 +1483,7 @@ OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); + 4 * sizeof(Expr *) * N); return new (Mem) OMPCopyprivateClause(N); } @@ -1399,16 +1511,42 @@ void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) { std::copy(A.begin(), A.end(), getFinals().begin()); } +void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) { + assert( + LHSExprs.size() == varlist_size() && + "Number of LHS expressions is not the same as the preallocated buffer"); + std::copy(LHSExprs.begin(), LHSExprs.end(), varlist_end()); +} + +void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) { + assert( + RHSExprs.size() == varlist_size() && + "Number of RHS expressions is not the same as the preallocated buffer"); + std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end()); +} + +void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) { + assert(ReductionOps.size() == varlist_size() && "Number of reduction " + "expressions is not the same " + "as the preallocated buffer"); + std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); +} + OMPReductionClause *OMPReductionClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, - NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) { + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, + ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, + ArrayRef<Expr *> ReductionOps) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); + 4 * sizeof(Expr *) * VL.size()); OMPReductionClause *Clause = new (Mem) OMPReductionClause( StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); Clause->setVarRefs(VL); + Clause->setLHSExprs(LHSExprs); + Clause->setRHSExprs(RHSExprs); + Clause->setReductionOps(ReductionOps); return Clause; } @@ -1416,7 +1554,7 @@ OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); + 4 * sizeof(Expr *) * N); return new (Mem) OMPReductionClause(N); } @@ -1443,10 +1581,7 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned 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); + auto &&I = getClausesOfKind(K); if (I) { auto *Clause = *I; @@ -1948,14 +2083,14 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, 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) { +OMPAtomicDirective *OMPAtomicDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, + Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + - 4 * sizeof(Stmt *)); + 5 * sizeof(Stmt *)); OMPAtomicDirective *Dir = new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -1963,6 +2098,9 @@ OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setX(X); Dir->setV(V); Dir->setExpr(E); + Dir->setUpdateExpr(UE); + Dir->IsXLHSInRHSPart = IsXLHSInRHSPart; + Dir->IsPostfixUpdate = IsPostfixUpdate; return Dir; } @@ -1972,7 +2110,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 4 * sizeof(Stmt *)); + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *)); return new (Mem) OMPAtomicDirective(NumClauses); } diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 927a679..db6d8c2 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -396,8 +396,9 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { } VisitStringLiteral(Node->getOutputConstraintLiteral(i)); - OS << " "; + OS << " ("; Visit(Node->getOutputExpr(i)); + OS << ")"; } // Inputs @@ -415,8 +416,9 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { } VisitStringLiteral(Node->getInputConstraintLiteral(i)); - OS << " "; + OS << " ("; Visit(Node->getInputExpr(i)); + OS << ")"; } // Clobbers @@ -1069,7 +1071,8 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { // Emit suffixes. Integer literals are always a builtin integer type. switch (Node->getType()->getAs<BuiltinType>()->getKind()) { default: llvm_unreachable("Unexpected type for integer literal!"); - case BuiltinType::SChar: OS << "i8"; break; + case BuiltinType::Char_S: + case BuiltinType::Char_U: OS << "i8"; break; case BuiltinType::UChar: OS << "Ui8"; break; case BuiltinType::Short: OS << "i16"; break; case BuiltinType::UShort: OS << "Ui16"; break; @@ -1373,34 +1376,37 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) { return; } - OS << "{ "; + OS << "{"; for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) { if (i) OS << ", "; if (Node->getInit(i)) PrintExpr(Node->getInit(i)); else - OS << "0"; + OS << "{}"; } - OS << " }"; + OS << "}"; } void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) { - OS << "( "; + OS << "("; for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) { if (i) OS << ", "; PrintExpr(Node->getExpr(i)); } - OS << " )"; + OS << ")"; } void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { + bool NeedsEquals = true; for (DesignatedInitExpr::designators_iterator D = Node->designators_begin(), DEnd = Node->designators_end(); D != DEnd; ++D) { if (D->isFieldDesignator()) { if (D->getDotLoc().isInvalid()) { - if (IdentifierInfo *II = D->getFieldName()) + if (IdentifierInfo *II = D->getFieldName()) { OS << II->getName() << ":"; + NeedsEquals = false; + } } else { OS << "." << D->getFieldName()->getName(); } @@ -1417,7 +1423,10 @@ void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { } } - OS << " = "; + if (NeedsEquals) + OS << " = "; + else + OS << " "; PrintExpr(Node->getInit()); } @@ -1621,6 +1630,15 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { const TemplateArgumentList *Args = cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs(); assert(Args); + + if (Args->size() != 1) { + OS << "operator \"\" " << Node->getUDSuffix()->getName(); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, Args->data(), Args->size(), Policy); + OS << "()"; + return; + } + const TemplateArgument &Pack = Args->get(0); for (const auto &P : Pack.pack_elements()) { char C = (char)P.getAsIntegral().getZExtValue(); @@ -1679,9 +1697,13 @@ void StmtPrinter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Node) { void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { Node->getType().print(OS, Policy); - OS << "("; + // If there are no parens, this is list-initialization, and the braces are + // part of the syntax of the inner construct. + if (Node->getLParenLoc().isValid()) + OS << "("; PrintExpr(Node->getSubExpr()); - OS << ")"; + if (Node->getLParenLoc().isValid()) + OS << ")"; } void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { @@ -1690,7 +1712,12 @@ void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { Node->getType().print(OS, Policy); - OS << "("; + if (Node->isStdInitListInitialization()) + /* Nothing to do; braces are part of creating the std::initializer_list. */; + else if (Node->isListInitialization()) + OS << "{"; + else + OS << "("; for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); Arg != ArgEnd; ++Arg) { @@ -1700,7 +1727,12 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { OS << ", "; PrintExpr(*Arg); } - OS << ")"; + if (Node->isStdInitListInitialization()) + /* See above. */; + else if (Node->isListInitialization()) + OS << "}"; + else + OS << ")"; } void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { @@ -1734,7 +1766,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { break; case LCK_ByRef: - if (Node->getCaptureDefault() != LCD_ByRef || C->isInitCapture()) + if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(C)) OS << '&'; OS << C->getCapturedVar()->getName(); break; @@ -1746,7 +1778,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { llvm_unreachable("VLA type in explicit captures."); } - if (C->isInitCapture()) + if (Node->isInitCapture(C)) PrintExpr(C->getCapturedVar()->getInit()); } OS << ']'; @@ -1866,8 +1898,8 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { } void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { - if (E->isListInitialization()) - OS << "{ "; + if (E->isListInitialization() && !E->isStdInitListInitialization()) + OS << "{"; for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { if (isa<CXXDefaultArgExpr>(E->getArg(i))) { @@ -1879,8 +1911,8 @@ void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { PrintExpr(E->getArg(i)); } - if (E->isListInitialization()) - OS << " }"; + if (E->isListInitialization() && !E->isStdInitListInitialization()) + OS << "}"; } void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index d1f25d6..c66b153 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -298,8 +298,12 @@ void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { } void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { } void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) { - if (C->getChunkSize()) + if (C->getChunkSize()) { Profiler->VisitStmt(C->getChunkSize()); + if (C->getHelperChunkSize()) { + Profiler->VisitStmt(C->getChunkSize()); + } + } } void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *) {} @@ -346,6 +350,15 @@ OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) { void OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) { VisitOMPClauseList(C); + for (auto *E : C->source_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->destination_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->assignment_ops()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) { VisitOMPClauseList(C); @@ -356,10 +369,29 @@ void OMPClauseProfiler::VisitOMPReductionClause( C->getQualifierLoc().getNestedNameSpecifier()); Profiler->VisitName(C->getNameInfo().getName()); VisitOMPClauseList(C); + for (auto *E : C->lhs_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->rhs_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->reduction_ops()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { VisitOMPClauseList(C); + for (auto *E : C->inits()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->updates()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->finals()) { + Profiler->VisitStmt(E); + } Profiler->VisitStmt(C->getStep()); + Profiler->VisitStmt(C->getCalcStep()); } void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) { VisitOMPClauseList(C); @@ -367,10 +399,28 @@ void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) { } void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) { VisitOMPClauseList(C); + for (auto *E : C->source_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->destination_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->assignment_ops()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) { VisitOMPClauseList(C); + for (auto *E : C->source_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->destination_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->assignment_ops()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) { VisitOMPClauseList(C); diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index e4f364d..09bb769 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -170,15 +170,7 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) - : Type(Vector, canonType, vecType->isDependentType(), - vecType->isInstantiationDependentType(), - vecType->isVariablyModifiedType(), - vecType->containsUnexpandedParameterPack()), - ElementType(vecType) -{ - VectorTypeBits.VecKind = vecKind; - VectorTypeBits.NumElements = nElements; -} + : VectorType(Vector, vecType, nElements, canonType, vecKind) {} VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) @@ -640,12 +632,13 @@ bool Type::hasIntegerRepresentation() const { bool Type::isIntegralType(ASTContext &Ctx) const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Int128; - + BT->getKind() <= BuiltinType::Int128; + + // Complete enum types are integral in C. if (!Ctx.getLangOpts().CPlusPlus) if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) - return ET->getDecl()->isComplete(); // Complete enum types are integral in C. - + return ET->getDecl()->isComplete(); + return false; } @@ -736,7 +729,7 @@ bool Type::isSignedIntegerType() const { bool Type::isSignedIntegerOrEnumerationType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) { return BT->getKind() >= BuiltinType::Char_S && - BT->getKind() <= BuiltinType::Int128; + BT->getKind() <= BuiltinType::Int128; } if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { @@ -1089,7 +1082,7 @@ bool QualType::isTrivialType(ASTContext &Context) const { bool QualType::isTriviallyCopyableType(ASTContext &Context) const { if ((*this)->isArrayType()) - return Context.getBaseElementType(*this).isTrivialType(Context); + return Context.getBaseElementType(*this).isTriviallyCopyableType(Context); if (Context.getLangOpts().ObjCAutoRefCount) { switch (getObjCLifetime()) { @@ -1586,8 +1579,9 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86_64SysV: return "sysv_abi"; case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; - case CC_PnaclCall: return "pnaclcall"; case CC_IntelOclBicc: return "intel_ocl_bicc"; + case CC_SpirFunction: return "spir_function"; + case CC_SpirKernel: return "spir_kernel"; } llvm_unreachable("Invalid calling convention."); @@ -1720,7 +1714,7 @@ bool FunctionProtoType::isNothrow(const ASTContext &Ctx, if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) return true; - if (EST == EST_Dynamic && ResultIfDependent == true) { + if (EST == EST_Dynamic && ResultIfDependent) { // A dynamic exception specification is throwing unless every exception // type is an (unexpanded) pack expansion type. for (unsigned I = 0, N = NumExceptions; I != N; ++I) @@ -1936,7 +1930,6 @@ bool AttributedType::isCallingConv() const { case attr_pascal: case attr_ms_abi: case attr_sysv_abi: - case attr_pnaclcall: case attr_inteloclbicc: return true; } @@ -2378,6 +2371,11 @@ bool Type::isObjCNSObjectType() const { return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>(); return false; } +bool Type::isObjCIndependentClassType() const { + if (const TypedefType *typedefType = dyn_cast<TypedefType>(this)) + return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>(); + return false; +} bool Type::isObjCRetainableType() const { return isObjCObjectPointerType() || isBlockPointerType() || diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index e36fc17..3928fe8 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -110,7 +110,7 @@ namespace { }; } -static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals) { +static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, bool C99) { bool appendSpace = false; if (TypeQuals & Qualifiers::Const) { OS << "const"; @@ -123,7 +123,11 @@ static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals) { } if (TypeQuals & Qualifiers::Restrict) { if (appendSpace) OS << ' '; - OS << "restrict"; + if (C99) { + OS << "restrict"; + } else { + OS << "__restrict"; + } } } @@ -432,7 +436,7 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T, raw_ostream &OS) { OS << '['; if (T->getIndexTypeQualifiers().hasQualifiers()) { - AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers()); + AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99); OS << ' '; } @@ -465,7 +469,7 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T, raw_ostream &OS) { OS << '['; if (T->getIndexTypeQualifiers().hasQualifiers()) { - AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers()); + AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99); OS << ' '; } @@ -685,9 +689,6 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_AAPCS_VFP: OS << " __attribute__((pcs(\"aapcs-vfp\")))"; break; - case CC_PnaclCall: - OS << " __attribute__((pnaclcall))"; - break; case CC_IntelOclBicc: OS << " __attribute__((intel_ocl_bicc))"; break; @@ -697,6 +698,10 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_X86_64SysV: OS << " __attribute__((sysv_abi))"; break; + case CC_SpirFunction: + case CC_SpirKernel: + // Do nothing. These CCs are not available as attributes. + break; } } @@ -708,7 +713,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, if (unsigned quals = T->getTypeQuals()) { OS << ' '; - AppendTypeQualList(OS, quals); + AppendTypeQualList(OS, quals, Policy.LangOpts.C99); } switch (T->getRefQualifier()) { @@ -1253,7 +1258,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, OS << ')'; break; } - case AttributedType::attr_pnaclcall: OS << "pnaclcall"; break; case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break; } OS << "))"; @@ -1473,7 +1477,7 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, unsigned quals = getCVRQualifiers(); if (quals) { - AppendTypeQualList(OS, quals); + AppendTypeQualList(OS, quals, Policy.LangOpts.C99); addSpace = true; } if (unsigned addrspace = getAddressSpace()) { diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp index ddb1f05..ca5f0aa 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp @@ -13,9 +13,11 @@ #include "clang/AST/VTableBuilder.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/SetOperations.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -216,7 +218,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, #endif } -static BaseOffset ComputeBaseOffset(ASTContext &Context, +static BaseOffset ComputeBaseOffset(const ASTContext &Context, const CXXRecordDecl *DerivedRD, const CXXBasePath &Path) { CharUnits NonVirtualOffset = CharUnits::Zero(); @@ -255,7 +257,7 @@ static BaseOffset ComputeBaseOffset(ASTContext &Context, } -static BaseOffset ComputeBaseOffset(ASTContext &Context, +static BaseOffset ComputeBaseOffset(const ASTContext &Context, const CXXRecordDecl *BaseRD, const CXXRecordDecl *DerivedRD) { CXXBasePaths Paths(/*FindAmbiguities=*/false, @@ -411,7 +413,8 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base, for (const auto *MD : RD->methods()) { if (!MD->isVirtual()) continue; - + MD = MD->getCanonicalDecl(); + OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset()); Out << " "; @@ -695,6 +698,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, for (const auto *MD : RD->methods()) { if (!MD->isVirtual()) continue; + MD = MD->getCanonicalDecl(); CharUnits OffsetOffset = getCurrentOffsetOffset(); @@ -1514,6 +1518,7 @@ void ItaniumVTableBuilder::AddMethods( for (const auto *MD : RD->methods()) { if (!MD->isVirtual()) continue; + MD = MD->getCanonicalDecl(); // Get the final overrider. FinalOverriders::OverriderInfo Overrider = @@ -2196,6 +2201,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { // We only want virtual member functions. if (!MD->isVirtual()) continue; + MD = MD->getCanonicalDecl(); std::string MethodName = PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, @@ -2585,7 +2591,9 @@ public: // Only include the RTTI component if we know that we will provide a // definition of the vftable. HasRTTIComponent = Context.getLangOpts().RTTIData && - !MostDerivedClass->hasAttr<DLLImportAttr>(); + !MostDerivedClass->hasAttr<DLLImportAttr>() && + MostDerivedClass->getTemplateSpecializationKind() != + TSK_ExplicitInstantiationDeclaration; LayoutVFTable(); @@ -2625,8 +2633,6 @@ public: void dumpLayout(raw_ostream &); }; -} // end namespace - /// InitialOverriddenDefinitionCollector - Finds the set of least derived bases /// that define the given method. struct InitialOverriddenDefinitionCollector { @@ -2641,6 +2647,8 @@ struct InitialOverriddenDefinitionCollector { } }; +} // end namespace + static bool BaseInSet(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *BasesSet) { BasesSetVectorTy *Bases = (BasesSetVectorTy *)BasesSet; @@ -2730,8 +2738,9 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) { CharUnits ThisOffset = Overrider.Offset; CharUnits LastVBaseOffset; - // For each path from the overrider to the parents of the overridden methods, - // traverse the path, calculating the this offset in the most derived class. + // For each path from the overrider to the parents of the overridden + // methods, traverse the path, calculating the this offset in the most + // derived class. for (int J = 0, F = Path.size(); J != F; ++J) { const CXXBasePathElement &Element = Path[J]; QualType CurTy = Element.Base->getType(); @@ -2930,6 +2939,7 @@ static void GroupNewVirtualOverloads( typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy; VisitedGroupIndicesTy VisitedGroupIndices; for (const auto *MD : RD->methods()) { + MD = MD->getCanonicalDecl(); VisitedGroupIndicesTy::iterator J; bool Inserted; std::tie(J, Inserted) = VisitedGroupIndices.insert( @@ -2962,7 +2972,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); // See if this class expands a vftable of the base we look at, which is either - // the one defined by the vfptr base path or the primary base of the current class. + // the one defined by the vfptr base path or the primary base of the current + // class. const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase; CharUnits NextBaseOffset; if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) { @@ -3020,7 +3031,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, ThisAdjustmentOffset); if (OverriddenMD) { - // If MD overrides anything in this vftable, we need to update the entries. + // If MD overrides anything in this vftable, we need to update the + // entries. MethodInfoMapTy::iterator OverriddenMDIterator = MethodInfoMap.find(OverriddenMD); @@ -3435,55 +3447,176 @@ 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; +namespace { +typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>, + llvm::DenseSet<BaseSubobject>> FullPathTy; +} + +// This recursive function finds all paths from a subobject centered at +// (RD, Offset) to the subobject located at BaseWithVPtr. +static void findPathsToSubobject(ASTContext &Context, + const ASTRecordLayout &MostDerivedLayout, + const CXXRecordDecl *RD, CharUnits Offset, + BaseSubobject BaseWithVPtr, + FullPathTy &FullPath, + std::list<FullPathTy> &Paths) { + if (BaseSubobject(RD, Offset) == BaseWithVPtr) { + Paths.push_back(FullPath); + return; } 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; + for (const CXXBaseSpecifier &BS : RD->bases()) { + const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl(); + CharUnits NewOffset = BS.isVirtual() + ? MostDerivedLayout.getVBaseClassOffset(Base) + : Offset + Layout.getBaseClassOffset(Base); + FullPath.insert(BaseSubobject(Base, NewOffset)); + findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset, + BaseWithVPtr, FullPath, Paths); FullPath.pop_back(); } - return false; +} + +// Return the paths which are not subsets of other paths. +static void removeRedundantPaths(std::list<FullPathTy> &FullPaths) { + FullPaths.remove_if([&](const FullPathTy &SpecificPath) { + for (const FullPathTy &OtherPath : FullPaths) { + if (&SpecificPath == &OtherPath) + continue; + if (std::all_of(SpecificPath.begin(), SpecificPath.end(), + [&](const BaseSubobject &BSO) { + return OtherPath.count(BSO) != 0; + })) { + return true; + } + } + return false; + }); +} + +static CharUnits getOffsetOfFullPath(ASTContext &Context, + const CXXRecordDecl *RD, + const FullPathTy &FullPath) { + const ASTRecordLayout &MostDerivedLayout = + Context.getASTRecordLayout(RD); + CharUnits Offset = CharUnits::fromQuantity(-1); + for (const BaseSubobject &BSO : FullPath) { + const CXXRecordDecl *Base = BSO.getBase(); + // The first entry in the path is always the most derived record, skip it. + if (Base == RD) { + assert(Offset.getQuantity() == -1); + Offset = CharUnits::Zero(); + continue; + } + assert(Offset.getQuantity() != -1); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + // While we know which base has to be traversed, we don't know if that base + // was a virtual base. + const CXXBaseSpecifier *BaseBS = std::find_if( + RD->bases_begin(), RD->bases_end(), [&](const CXXBaseSpecifier &BS) { + return BS.getType()->getAsCXXRecordDecl() == Base; + }); + Offset = BaseBS->isVirtual() ? MostDerivedLayout.getVBaseClassOffset(Base) + : Offset + Layout.getBaseClassOffset(Base); + RD = Base; + } + return Offset; +} + +// We want to select the path which introduces the most covariant overrides. If +// two paths introduce overrides which the other path doesn't contain, issue a +// diagnostic. +static const FullPathTy *selectBestPath(ASTContext &Context, + const CXXRecordDecl *RD, VPtrInfo *Info, + std::list<FullPathTy> &FullPaths) { + // Handle some easy cases first. + if (FullPaths.empty()) + return nullptr; + if (FullPaths.size() == 1) + return &FullPaths.front(); + + const FullPathTy *BestPath = nullptr; + typedef std::set<const CXXMethodDecl *> OverriderSetTy; + OverriderSetTy LastOverrides; + for (const FullPathTy &SpecificPath : FullPaths) { + assert(!SpecificPath.empty()); + OverriderSetTy CurrentOverrides; + const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase(); + // Find the distance from the start of the path to the subobject with the + // VPtr. + CharUnits BaseOffset = + getOffsetOfFullPath(Context, TopLevelRD, SpecificPath); + FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD); + for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) { + if (!MD->isVirtual()) + continue; + FinalOverriders::OverriderInfo OI = + Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset); + const CXXMethodDecl *OverridingMethod = OI.Method; + // Only overriders which have a return adjustment introduce problematic + // thunks. + if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD) + .isEmpty()) + continue; + // It's possible that the overrider isn't in this path. If so, skip it + // because this path didn't introduce it. + const CXXRecordDecl *OverridingParent = OverridingMethod->getParent(); + if (std::none_of(SpecificPath.begin(), SpecificPath.end(), + [&](const BaseSubobject &BSO) { + return BSO.getBase() == OverridingParent; + })) + continue; + CurrentOverrides.insert(OverridingMethod); + } + OverriderSetTy NewOverrides = + llvm::set_difference(CurrentOverrides, LastOverrides); + if (NewOverrides.empty()) + continue; + OverriderSetTy MissingOverrides = + llvm::set_difference(LastOverrides, CurrentOverrides); + if (MissingOverrides.empty()) { + // This path is a strict improvement over the last path, let's use it. + BestPath = &SpecificPath; + std::swap(CurrentOverrides, LastOverrides); + } else { + // This path introduces an overrider with a conflicting covariant thunk. + DiagnosticsEngine &Diags = Context.getDiagnostics(); + const CXXMethodDecl *CovariantMD = *NewOverrides.begin(); + const CXXMethodDecl *ConflictMD = *MissingOverrides.begin(); + Diags.Report(RD->getLocation(), diag::err_vftable_ambiguous_component) + << RD; + Diags.Report(CovariantMD->getLocation(), diag::note_covariant_thunk) + << CovariantMD; + Diags.Report(ConflictMD->getLocation(), diag::note_covariant_thunk) + << ConflictMD; + } + } + // Go with the path that introduced the most covariant overrides. If there is + // no such path, pick the first path. + return BestPath ? BestPath : &FullPaths.front(); } 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; + FullPathTy FullPath; + std::list<FullPathTy> FullPaths; for (VPtrInfo *Info : Paths) { - findPathForVPtr(Context, MostDerivedLayout, RD, CharUnits::Zero(), - VBasesSeen, FullPath, Info); - VBasesSeen.clear(); + findPathsToSubobject( + Context, MostDerivedLayout, RD, CharUnits::Zero(), + BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath, + FullPaths); FullPath.clear(); + removeRedundantPaths(FullPaths); + Info->PathToBaseWithVPtr.clear(); + if (const FullPathTy *BestPath = + selectBestPath(Context, RD, Info, FullPaths)) + for (const BaseSubobject &BSO : *BestPath) + Info->PathToBaseWithVPtr.push_back(BSO.getBase()); + FullPaths.clear(); } } |