diff options
Diffstat (limited to 'lib/AST')
40 files changed, 9583 insertions, 5368 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 3d0d1e666c..fae1cf863c 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -796,11 +796,10 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), CompCategories(this_()), LastSDM(nullptr, 0) { TUDecl = TranslationUnitDecl::Create(*this); + TraversalScope = {TUDecl}; } ASTContext::~ASTContext() { - ReleaseParentMapEntries(); - // Release the DenseMaps associated with DeclContext objects. // FIXME: Is this the ideal solution? ReleaseDeclContextMaps(); @@ -838,22 +837,80 @@ ASTContext::~ASTContext() { Value.second->~PerModuleInitializers(); } -void ASTContext::ReleaseParentMapEntries() { - if (!PointerParents) return; - for (const auto &Entry : *PointerParents) { - if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { - delete Entry.second.get<ast_type_traits::DynTypedNode *>(); - } else if (Entry.second.is<ParentVector *>()) { - delete Entry.second.get<ParentVector *>(); +class ASTContext::ParentMap { + /// Contains parents of a node. + using ParentVector = llvm::SmallVector<ast_type_traits::DynTypedNode, 2>; + + /// Maps from a node to its parents. This is used for nodes that have + /// pointer identity only, which are more common and we can save space by + /// only storing a unique pointer to them. + using ParentMapPointers = llvm::DenseMap< + const void *, + llvm::PointerUnion4<const Decl *, const Stmt *, + ast_type_traits::DynTypedNode *, ParentVector *>>; + + /// Parent map for nodes without pointer identity. We store a full + /// DynTypedNode for all keys. + using ParentMapOtherNodes = llvm::DenseMap< + ast_type_traits::DynTypedNode, + llvm::PointerUnion4<const Decl *, const Stmt *, + ast_type_traits::DynTypedNode *, ParentVector *>>; + + ParentMapPointers PointerParents; + ParentMapOtherNodes OtherParents; + class ASTVisitor; + + static ast_type_traits::DynTypedNode + getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) { + if (const auto *D = U.dyn_cast<const Decl *>()) + return ast_type_traits::DynTypedNode::create(*D); + if (const auto *S = U.dyn_cast<const Stmt *>()) + return ast_type_traits::DynTypedNode::create(*S); + return *U.get<ast_type_traits::DynTypedNode *>(); + } + + template <typename NodeTy, typename MapTy> + static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, + const MapTy &Map) { + auto I = Map.find(Node); + if (I == Map.end()) { + return llvm::ArrayRef<ast_type_traits::DynTypedNode>(); + } + if (const auto *V = I->second.template dyn_cast<ParentVector *>()) { + return llvm::makeArrayRef(*V); + } + return getSingleDynTypedNodeFromParentMap(I->second); + } + +public: + ParentMap(ASTContext &Ctx); + ~ParentMap() { + for (const auto &Entry : PointerParents) { + if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { + delete Entry.second.get<ast_type_traits::DynTypedNode *>(); + } else if (Entry.second.is<ParentVector *>()) { + delete Entry.second.get<ParentVector *>(); + } } - } - for (const auto &Entry : *OtherParents) { - if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { - delete Entry.second.get<ast_type_traits::DynTypedNode *>(); - } else if (Entry.second.is<ParentVector *>()) { - delete Entry.second.get<ParentVector *>(); + for (const auto &Entry : OtherParents) { + if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { + delete Entry.second.get<ast_type_traits::DynTypedNode *>(); + } else if (Entry.second.is<ParentVector *>()) { + delete Entry.second.get<ParentVector *>(); + } } } + + DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node) { + if (Node.getNodeKind().hasPointerIdentity()) + return getDynNodeFromMap(Node.getMemoizationData(), PointerParents); + return getDynNodeFromMap(Node, OtherParents); + } +}; + +void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) { + TraversalScope = TopLevelDecls; + Parents.reset(); } void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { @@ -1241,6 +1298,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, InitBuiltinType(OCLClkEventTy, BuiltinType::OCLClkEvent); InitBuiltinType(OCLQueueTy, BuiltinType::OCLQueue); InitBuiltinType(OCLReserveIDTy, BuiltinType::OCLReserveID); + +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + InitBuiltinType(Id##Ty, BuiltinType::Id); +#include "clang/Basic/OpenCLExtensionTypes.def" } // Builtin type for __objc_yes and __objc_no @@ -1892,6 +1953,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" AS = getTargetAddressSpace( Target->getOpenCLTypeAddrSpace(getOpenCLTypeKind(T))); Width = Target->getPointerWidth(AS); @@ -2295,12 +2359,11 @@ structHasUniqueObjectRepresentations(const ASTContext &Context, } } - llvm::sort( - Bases.begin(), Bases.end(), [&](const std::pair<QualType, int64_t> &L, - const std::pair<QualType, int64_t> &R) { - return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) < - Layout.getBaseClassOffset(R.first->getAsCXXRecordDecl()); - }); + llvm::sort(Bases, [&](const std::pair<QualType, int64_t> &L, + const std::pair<QualType, int64_t> &R) { + return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) < + Layout.getBaseClassOffset(R.first->getAsCXXRecordDecl()); + }); for (const auto Base : Bases) { int64_t BaseOffset = Context.toBits( @@ -3698,30 +3761,20 @@ QualType ASTContext::getFunctionTypeInternal( assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - // FunctionProtoType objects are allocated with extra bytes after - // them for three variable size arrays at the end: - // - parameter types - // - exception types - // - extended parameter information - // Instead of the exception types, there could be a noexcept - // expression, or information used to resolve the exception - // specification. - size_t Size = - sizeof(FunctionProtoType) + NumArgs * sizeof(QualType) + - FunctionProtoType::getExceptionSpecSize( - EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size()); - - // Put the ExtParameterInfos last. If all were equal, it would make - // more sense to put these before the exception specification, because - // it's much easier to skip past them compared to the elaborate switch - // required to skip the exception specification. However, all is not - // equal; ExtParameterInfos are used to model very uncommon features, - // and it's better not to burden the more common paths. - if (EPI.ExtParameterInfos) { - Size += NumArgs * sizeof(FunctionProtoType::ExtParameterInfo); - } - - auto *FTP = (FunctionProtoType *) Allocate(Size, TypeAlignment); + // Compute the needed size to hold this FunctionProtoType and the + // various trailing objects. + auto ESH = FunctionProtoType::getExceptionSpecSize( + EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size()); + size_t Size = FunctionProtoType::totalSizeToAlloc< + QualType, FunctionType::FunctionTypeExtraBitfields, + FunctionType::ExceptionType, Expr *, FunctionDecl *, + FunctionProtoType::ExtParameterInfo, Qualifiers>( + NumArgs, FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type), + ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr, + EPI.ExtParameterInfos ? NumArgs : 0, + EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0); + + auto *FTP = (FunctionProtoType *)Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); @@ -5103,7 +5156,7 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2) { return true; } - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { const auto *T1OPType = T1->getAs<ObjCObjectPointerType>(); const auto *T2OPType = T2->getAs<ObjCObjectPointerType>(); if (T1OPType && T2OPType) { @@ -5767,50 +5820,86 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { } TypedefDecl *ASTContext::getCFConstantStringDecl() const { - if (!CFConstantStringTypeDecl) { - assert(!CFConstantStringTagDecl && - "tag and typedef should be initialized together"); - CFConstantStringTagDecl = buildImplicitRecord("__NSConstantString_tag"); - CFConstantStringTagDecl->startDefinition(); - - QualType FieldTypes[4]; - const char *FieldNames[4]; - - // const int *isa; - FieldTypes[0] = getPointerType(IntTy.withConst()); - FieldNames[0] = "isa"; - // int flags; - FieldTypes[1] = IntTy; - FieldNames[1] = "flags"; - // const char *str; - FieldTypes[2] = getPointerType(CharTy.withConst()); - FieldNames[2] = "str"; - // long length; - FieldTypes[3] = LongTy; - FieldNames[3] = "length"; - - // Create fields - for (unsigned i = 0; i < 4; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTagDecl, - SourceLocation(), - SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/nullptr, - /*BitWidth=*/nullptr, - /*Mutable=*/false, - ICIS_NoInit); - Field->setAccess(AS_public); - CFConstantStringTagDecl->addDecl(Field); - } + if (CFConstantStringTypeDecl) + return CFConstantStringTypeDecl; + + assert(!CFConstantStringTagDecl && + "tag and typedef should be initialized together"); + CFConstantStringTagDecl = buildImplicitRecord("__NSConstantString_tag"); + CFConstantStringTagDecl->startDefinition(); - CFConstantStringTagDecl->completeDefinition(); - // This type is designed to be compatible with NSConstantString, but cannot - // use the same name, since NSConstantString is an interface. - auto tagType = getTagDeclType(CFConstantStringTagDecl); - CFConstantStringTypeDecl = - buildImplicitTypedef(tagType, "__NSConstantString"); + struct { + QualType Type; + const char *Name; + } Fields[5]; + unsigned Count = 0; + + /// Objective-C ABI + /// + /// typedef struct __NSConstantString_tag { + /// const int *isa; + /// int flags; + /// const char *str; + /// long length; + /// } __NSConstantString; + /// + /// Swift ABI (4.1, 4.2) + /// + /// typedef struct __NSConstantString_tag { + /// uintptr_t _cfisa; + /// uintptr_t _swift_rc; + /// _Atomic(uint64_t) _cfinfoa; + /// const char *_ptr; + /// uint32_t _length; + /// } __NSConstantString; + /// + /// Swift ABI (5.0) + /// + /// typedef struct __NSConstantString_tag { + /// uintptr_t _cfisa; + /// uintptr_t _swift_rc; + /// _Atomic(uint64_t) _cfinfoa; + /// const char *_ptr; + /// uintptr_t _length; + /// } __NSConstantString; + + const auto CFRuntime = getLangOpts().CFRuntime; + if (static_cast<unsigned>(CFRuntime) < + static_cast<unsigned>(LangOptions::CoreFoundationABI::Swift)) { + Fields[Count++] = { getPointerType(IntTy.withConst()), "isa" }; + Fields[Count++] = { IntTy, "flags" }; + Fields[Count++] = { getPointerType(CharTy.withConst()), "str" }; + Fields[Count++] = { LongTy, "length" }; + } else { + Fields[Count++] = { getUIntPtrType(), "_cfisa" }; + Fields[Count++] = { getUIntPtrType(), "_swift_rc" }; + Fields[Count++] = { getFromTargetType(Target->getUInt64Type()), "_swift_rc" }; + Fields[Count++] = { getPointerType(CharTy.withConst()), "_ptr" }; + if (CFRuntime == LangOptions::CoreFoundationABI::Swift4_1 || + CFRuntime == LangOptions::CoreFoundationABI::Swift4_2) + Fields[Count++] = { IntTy, "_ptr" }; + else + Fields[Count++] = { getUIntPtrType(), "_ptr" }; + } + + // Create fields + for (unsigned i = 0; i < Count; ++i) { + FieldDecl *Field = + FieldDecl::Create(*this, CFConstantStringTagDecl, SourceLocation(), + SourceLocation(), &Idents.get(Fields[i].Name), + Fields[i].Type, /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); + Field->setAccess(AS_public); + CFConstantStringTagDecl->addDecl(Field); } + CFConstantStringTagDecl->completeDefinition(); + // This type is designed to be compatible with NSConstantString, but cannot + // use the same name, since NSConstantString is an interface. + auto tagType = getTagDeclType(CFConstantStringTagDecl); + CFConstantStringTypeDecl = + buildImplicitTypedef(tagType, "__NSConstantString"); + return CFConstantStringTypeDecl; } @@ -6004,7 +6093,7 @@ bool ASTContext::BlockRequiresCopying(QualType Ty, bool ASTContext::getByrefLifetime(QualType Ty, Qualifiers::ObjCLifetime &LifeTime, bool &HasByrefExtendedLayout) const { - if (!getLangOpts().ObjC1 || + if (!getLangOpts().ObjC || getLangOpts().getGC() != LangOptions::NonGC) return false; @@ -6476,6 +6565,9 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: @@ -7682,7 +7774,7 @@ Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const { if (getLangOpts().getGC() == LangOptions::NonGC) return Qualifiers::GCNone; - assert(getLangOpts().ObjC1); + assert(getLangOpts().ObjC); Qualifiers::GC GCAttrs = Ty.getObjCGCAttr(); // Default behaviour under objective-C's gc is for ObjC pointers @@ -8038,7 +8130,7 @@ void getIntersectionOfProtocols(ASTContext &Context, // Also add the protocols associated with the LHS interface. Context.CollectInheritedProtocols(LHS->getInterface(), LHSProtocolSet); - // Add all of the protocls for the RHS. + // Add all of the protocols for the RHS. llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSProtocolSet; // Start with the protocol qualifiers. @@ -9826,10 +9918,10 @@ void ASTContext::forEachMultiversionedFunctionVersion( llvm::function_ref<void(FunctionDecl *)> Pred) const { assert(FD->isMultiVersion() && "Only valid for multiversioned functions"); llvm::SmallDenseSet<const FunctionDecl*, 4> SeenDecls; - FD = FD->getCanonicalDecl(); + FD = FD->getMostRecentDecl(); for (auto *CurDecl : FD->getDeclContext()->getRedeclContext()->lookup(FD->getDeclName())) { - FunctionDecl *CurFD = CurDecl->getAsFunction()->getCanonicalDecl(); + FunctionDecl *CurFD = CurDecl->getAsFunction()->getMostRecentDecl(); if (CurFD && hasSameType(CurFD->getType(), FD->getType()) && std::end(SeenDecls) == llvm::find(SeenDecls, CurFD)) { SeenDecls.insert(CurFD); @@ -10066,21 +10158,10 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { return (Size != Align || toBits(sizeChars) > MaxInlineWidthInBits); } -static ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap( - ASTContext::ParentMapPointers::mapped_type U) { - if (const auto *D = U.dyn_cast<const Decl *>()) - return ast_type_traits::DynTypedNode::create(*D); - if (const auto *S = U.dyn_cast<const Stmt *>()) - return ast_type_traits::DynTypedNode::create(*S); - return *U.get<ast_type_traits::DynTypedNode *>(); -} - -namespace { - /// Template specializations to abstract away from pointers and TypeLocs. /// @{ template <typename T> -ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) { +static ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) { return ast_type_traits::DynTypedNode::create(*Node); } template <> @@ -10094,160 +10175,121 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { } /// @} - /// A \c RecursiveASTVisitor that builds a map from nodes to their - /// parents as defined by the \c RecursiveASTVisitor. - /// - /// Note that the relationship described here is purely in terms of AST - /// traversal - there are other relationships (for example declaration context) - /// in the AST that are better modeled by special matchers. - /// - /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. - class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> { - public: - /// Builds and returns the translation unit's parent map. - /// - /// The caller takes ownership of the returned \c ParentMap. - static std::pair<ASTContext::ParentMapPointers *, - ASTContext::ParentMapOtherNodes *> - buildMap(TranslationUnitDecl &TU) { - ParentMapASTVisitor Visitor(new ASTContext::ParentMapPointers, - new ASTContext::ParentMapOtherNodes); - Visitor.TraverseDecl(&TU); - return std::make_pair(Visitor.Parents, Visitor.OtherParents); - } +/// A \c RecursiveASTVisitor that builds a map from nodes to their +/// parents as defined by the \c RecursiveASTVisitor. +/// +/// Note that the relationship described here is purely in terms of AST +/// traversal - there are other relationships (for example declaration context) +/// in the AST that are better modeled by special matchers. +/// +/// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. +class ASTContext::ParentMap::ASTVisitor + : public RecursiveASTVisitor<ASTVisitor> { +public: + ASTVisitor(ParentMap &Map) : Map(Map) {} - private: - friend class RecursiveASTVisitor<ParentMapASTVisitor>; +private: + friend class RecursiveASTVisitor<ASTVisitor>; - using VisitorBase = RecursiveASTVisitor<ParentMapASTVisitor>; + using VisitorBase = RecursiveASTVisitor<ASTVisitor>; - ParentMapASTVisitor(ASTContext::ParentMapPointers *Parents, - ASTContext::ParentMapOtherNodes *OtherParents) - : Parents(Parents), OtherParents(OtherParents) {} + bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitTemplateInstantiations() const { - return true; - } + bool shouldVisitImplicitCode() const { return true; } - bool shouldVisitImplicitCode() const { + template <typename T, typename MapNodeTy, typename BaseTraverseFn, + typename MapTy> + bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse, + MapTy *Parents) { + if (!Node) return true; - } - - template <typename T, typename MapNodeTy, typename BaseTraverseFn, - typename MapTy> - bool TraverseNode(T Node, MapNodeTy MapNode, - BaseTraverseFn BaseTraverse, MapTy *Parents) { - if (!Node) - return true; - if (ParentStack.size() > 0) { - // FIXME: Currently we add the same parent multiple times, but only - // when no memoization data is available for the type. - // For example when we visit all subexpressions of template - // instantiations; this is suboptimal, but benign: the only way to - // visit those is with hasAncestor / hasParent, and those do not create - // new matches. - // The plan is to enable DynTypedNode to be storable in a map or hash - // map. The main problem there is to implement hash functions / - // comparison operators for all types that DynTypedNode supports that - // do not have pointer identity. - auto &NodeOrVector = (*Parents)[MapNode]; - if (NodeOrVector.isNull()) { - if (const auto *D = ParentStack.back().get<Decl>()) - NodeOrVector = D; - else if (const auto *S = ParentStack.back().get<Stmt>()) - NodeOrVector = S; - else - NodeOrVector = - new ast_type_traits::DynTypedNode(ParentStack.back()); - } else { - if (!NodeOrVector.template is<ASTContext::ParentVector *>()) { - auto *Vector = new ASTContext::ParentVector( - 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); - delete NodeOrVector - .template dyn_cast<ast_type_traits::DynTypedNode *>(); - NodeOrVector = Vector; - } - - auto *Vector = - NodeOrVector.template get<ASTContext::ParentVector *>(); - // Skip duplicates for types that have memoization data. - // We must check that the type has memoization data before calling - // std::find() because DynTypedNode::operator== can't compare all - // types. - bool Found = ParentStack.back().getMemoizationData() && - std::find(Vector->begin(), Vector->end(), - ParentStack.back()) != Vector->end(); - if (!Found) - Vector->push_back(ParentStack.back()); + if (ParentStack.size() > 0) { + // FIXME: Currently we add the same parent multiple times, but only + // when no memoization data is available for the type. + // For example when we visit all subexpressions of template + // instantiations; this is suboptimal, but benign: the only way to + // visit those is with hasAncestor / hasParent, and those do not create + // new matches. + // The plan is to enable DynTypedNode to be storable in a map or hash + // map. The main problem there is to implement hash functions / + // comparison operators for all types that DynTypedNode supports that + // do not have pointer identity. + auto &NodeOrVector = (*Parents)[MapNode]; + if (NodeOrVector.isNull()) { + if (const auto *D = ParentStack.back().get<Decl>()) + NodeOrVector = D; + else if (const auto *S = ParentStack.back().get<Stmt>()) + NodeOrVector = S; + else + NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back()); + } else { + if (!NodeOrVector.template is<ParentVector *>()) { + auto *Vector = new ParentVector( + 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); + delete NodeOrVector + .template dyn_cast<ast_type_traits::DynTypedNode *>(); + NodeOrVector = Vector; } - } - ParentStack.push_back(createDynTypedNode(Node)); - bool Result = BaseTraverse(); - ParentStack.pop_back(); - return Result; - } - bool TraverseDecl(Decl *DeclNode) { - return TraverseNode(DeclNode, DeclNode, - [&] { return VisitorBase::TraverseDecl(DeclNode); }, - Parents); + auto *Vector = NodeOrVector.template get<ParentVector *>(); + // Skip duplicates for types that have memoization data. + // We must check that the type has memoization data before calling + // std::find() because DynTypedNode::operator== can't compare all + // types. + bool Found = ParentStack.back().getMemoizationData() && + std::find(Vector->begin(), Vector->end(), + ParentStack.back()) != Vector->end(); + if (!Found) + Vector->push_back(ParentStack.back()); + } } + ParentStack.push_back(createDynTypedNode(Node)); + bool Result = BaseTraverse(); + ParentStack.pop_back(); + return Result; + } - bool TraverseStmt(Stmt *StmtNode) { - return TraverseNode(StmtNode, StmtNode, - [&] { return VisitorBase::TraverseStmt(StmtNode); }, - Parents); - } + bool TraverseDecl(Decl *DeclNode) { + return TraverseNode( + DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); }, + &Map.PointerParents); + } - bool TraverseTypeLoc(TypeLoc TypeLocNode) { - return TraverseNode( - TypeLocNode, ast_type_traits::DynTypedNode::create(TypeLocNode), - [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, - OtherParents); - } + bool TraverseStmt(Stmt *StmtNode) { + return TraverseNode( + StmtNode, StmtNode, [&] { return VisitorBase::TraverseStmt(StmtNode); }, + &Map.PointerParents); + } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { - return TraverseNode( - NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode), - [&] { - return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); - }, - OtherParents); - } + bool TraverseTypeLoc(TypeLoc TypeLocNode) { + return TraverseNode( + TypeLocNode, ast_type_traits::DynTypedNode::create(TypeLocNode), + [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, + &Map.OtherParents); + } - ASTContext::ParentMapPointers *Parents; - ASTContext::ParentMapOtherNodes *OtherParents; - llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack; - }; + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { + return TraverseNode( + NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode), + [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); }, + &Map.OtherParents); + } -} // namespace + ParentMap ⤅ + llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack; +}; -template <typename NodeTy, typename MapTy> -static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, - const MapTy &Map) { - auto I = Map.find(Node); - if (I == Map.end()) { - return llvm::ArrayRef<ast_type_traits::DynTypedNode>(); - } - if (const auto *V = - I->second.template dyn_cast<ASTContext::ParentVector *>()) { - return llvm::makeArrayRef(*V); - } - return getSingleDynTypedNodeFromParentMap(I->second); +ASTContext::ParentMap::ParentMap(ASTContext &Ctx) { + ASTVisitor(*this).TraverseAST(Ctx); } ASTContext::DynTypedNodeList ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { - if (!PointerParents) { - // We always need to run over the whole translation unit, as + if (!Parents) + // We build the parent map for the traversal scope (usually whole TU), as // hasAncestor can escape any subtree. - auto Maps = ParentMapASTVisitor::buildMap(*getTranslationUnitDecl()); - PointerParents.reset(Maps.first); - OtherParents.reset(Maps.second); - } - if (Node.getNodeKind().hasPointerIdentity()) - return getDynNodeFromMap(Node.getMemoizationData(), *PointerParents); - return getDynNodeFromMap(Node, *OtherParents); + Parents = llvm::make_unique<ParentMap>(*this); + return Parents->getParents(Node); } bool diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 38a2fe9caf..43d8d7d38f 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDumperUtils.h" #include "clang/AST/Attr.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/DeclCXX.h" @@ -22,6 +23,7 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/LocInfoType.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/TextNodeDumper.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/Module.h" @@ -35,178 +37,32 @@ using namespace clang::comments; //===----------------------------------------------------------------------===// namespace { - // Colors used for various parts of the AST dump - // Do not use bold yellow for any text. It is hard to read on white screens. - struct TerminalColor { - raw_ostream::Colors Color; - bool Bold; - }; + class ASTDumper + : public ConstDeclVisitor<ASTDumper>, + public ConstStmtVisitor<ASTDumper>, + public ConstCommentVisitor<ASTDumper, void, const FullComment *>, + public TypeVisitor<ASTDumper> { - // Red - CastColor - // Green - TypeColor - // Bold Green - DeclKindNameColor, UndeserializedColor - // Yellow - AddressColor, LocationColor - // Blue - CommentColor, NullColor, IndentColor - // Bold Blue - AttrColor - // Bold Magenta - StmtColor - // Cyan - ValueKindColor, ObjectKindColor - // Bold Cyan - ValueColor, DeclNameColor - - // Decl kind names (VarDecl, FunctionDecl, etc) - static const TerminalColor DeclKindNameColor = { raw_ostream::GREEN, true }; - // Attr names (CleanupAttr, GuardedByAttr, etc) - static const TerminalColor AttrColor = { raw_ostream::BLUE, true }; - // Statement names (DeclStmt, ImplicitCastExpr, etc) - static const TerminalColor StmtColor = { raw_ostream::MAGENTA, true }; - // Comment names (FullComment, ParagraphComment, TextComment, etc) - static const TerminalColor CommentColor = { raw_ostream::BLUE, false }; - - // Type names (int, float, etc, plus user defined types) - static const TerminalColor TypeColor = { raw_ostream::GREEN, false }; - - // Pointer address - static const TerminalColor AddressColor = { raw_ostream::YELLOW, false }; - // Source locations - static const TerminalColor LocationColor = { raw_ostream::YELLOW, false }; - - // lvalue/xvalue - static const TerminalColor ValueKindColor = { raw_ostream::CYAN, false }; - // bitfield/objcproperty/objcsubscript/vectorcomponent - static const TerminalColor ObjectKindColor = { raw_ostream::CYAN, false }; - - // Null statements - static const TerminalColor NullColor = { raw_ostream::BLUE, false }; - - // Undeserialized entities - static const TerminalColor UndeserializedColor = { raw_ostream::GREEN, true }; - - // CastKind from CastExpr's - static const TerminalColor CastColor = { raw_ostream::RED, false }; - - // Value of the statement - static const TerminalColor ValueColor = { raw_ostream::CYAN, true }; - // Decl names - static const TerminalColor DeclNameColor = { raw_ostream::CYAN, true }; - - // Indents ( `, -. | ) - static const TerminalColor IndentColor = { raw_ostream::BLUE, false }; + TextTreeStructure TreeStructure; + TextNodeDumper NodeDumper; - class ASTDumper - : public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>, - public ConstCommentVisitor<ASTDumper>, public TypeVisitor<ASTDumper> { raw_ostream &OS; - const CommandTraits *Traits; - const SourceManager *SM; /// The policy to use for printing; can be defaulted. PrintingPolicy PrintPolicy; - /// Pending[i] is an action to dump an entity at level i. - llvm::SmallVector<std::function<void(bool isLastChild)>, 32> Pending; - /// Indicates whether we should trigger deserialization of nodes that had /// not already been loaded. bool Deserialize = false; - /// Indicates whether we're at the top level. - bool TopLevel = true; - - /// Indicates if we're handling the first child after entering a new depth. - bool FirstChild = true; - - /// Prefix for currently-being-dumped entity. - std::string Prefix; - - /// Keep track of the last location we print out so that we can - /// print out deltas from then on out. - const char *LastLocFilename = ""; - unsigned LastLocLine = ~0U; - - /// The \c FullComment parent of the comment being dumped. - const FullComment *FC = nullptr; - - bool ShowColors; + const bool ShowColors; /// Dump a child of the current node. template<typename Fn> void dumpChild(Fn doDumpChild) { - // If we're at the top level, there's nothing interesting to do; just - // run the dumper. - if (TopLevel) { - TopLevel = false; - doDumpChild(); - while (!Pending.empty()) { - Pending.back()(true); - Pending.pop_back(); - } - Prefix.clear(); - OS << "\n"; - TopLevel = true; - return; - } - - const FullComment *OrigFC = FC; - auto dumpWithIndent = [this, doDumpChild, OrigFC](bool isLastChild) { - // Print out the appropriate tree structure and work out the prefix for - // children of this node. For instance: - // - // A Prefix = "" - // |-B Prefix = "| " - // | `-C Prefix = "| " - // `-D Prefix = " " - // |-E Prefix = " | " - // `-F Prefix = " " - // G Prefix = "" - // - // Note that the first level gets no prefix. - { - OS << '\n'; - ColorScope Color(*this, IndentColor); - OS << Prefix << (isLastChild ? '`' : '|') << '-'; - this->Prefix.push_back(isLastChild ? ' ' : '|'); - this->Prefix.push_back(' '); - } - - FirstChild = true; - unsigned Depth = Pending.size(); - - FC = OrigFC; - doDumpChild(); - - // If any children are left, they're the last at their nesting level. - // Dump those ones out now. - while (Depth < Pending.size()) { - Pending.back()(true); - this->Pending.pop_back(); - } - - // Restore the old prefix. - this->Prefix.resize(Prefix.size() - 2); - }; - - if (FirstChild) { - Pending.push_back(std::move(dumpWithIndent)); - } else { - Pending.back()(false); - Pending.back() = std::move(dumpWithIndent); - } - FirstChild = false; + TreeStructure.addChild(doDumpChild); } - class ColorScope { - ASTDumper &Dumper; - public: - ColorScope(ASTDumper &Dumper, TerminalColor Color) - : Dumper(Dumper) { - if (Dumper.ShowColors) - Dumper.OS.changeColor(Color.Color, Color.Bold); - } - ~ColorScope() { - if (Dumper.ShowColors) - Dumper.OS.resetColor(); - } - }; - public: ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) @@ -219,40 +75,43 @@ namespace { ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM, bool ShowColors, const PrintingPolicy &PrintPolicy) - : OS(OS), Traits(Traits), SM(SM), PrintPolicy(PrintPolicy), - ShowColors(ShowColors) {} + : TreeStructure(OS, ShowColors), + NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS), + PrintPolicy(PrintPolicy), ShowColors(ShowColors) {} void setDeserialize(bool D) { Deserialize = D; } void dumpDecl(const Decl *D); void dumpStmt(const Stmt *S); - void dumpFullComment(const FullComment *C); // Utilities - void dumpPointer(const void *Ptr); - void dumpSourceRange(SourceRange R); - void dumpLocation(SourceLocation Loc); - void dumpBareType(QualType T, bool Desugar = true); - void dumpType(QualType T); + void dumpType(QualType T) { NodeDumper.dumpType(T); } void dumpTypeAsChild(QualType T); void dumpTypeAsChild(const Type *T); - void dumpBareDeclRef(const Decl *Node); void dumpDeclRef(const Decl *Node, const char *Label = nullptr); - void dumpName(const NamedDecl *D); - bool hasNodes(const DeclContext *DC); + void dumpBareDeclRef(const Decl *Node) { NodeDumper.dumpBareDeclRef(Node); } void dumpDeclContext(const DeclContext *DC); void dumpLookups(const DeclContext *DC, bool DumpDecls); void dumpAttr(const Attr *A); // C++ Utilities - void dumpAccessSpecifier(AccessSpecifier AS); void dumpCXXCtorInitializer(const CXXCtorInitializer *Init); void dumpTemplateParameters(const TemplateParameterList *TPL); void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI); - void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A); + void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A, + const Decl *From = nullptr, + const char *Label = nullptr); void dumpTemplateArgumentList(const TemplateArgumentList &TAL); void dumpTemplateArgument(const TemplateArgument &A, - SourceRange R = SourceRange()); + SourceRange R = SourceRange(), + const Decl *From = nullptr, + const char *Label = nullptr); + template <typename SpecializationDecl> + void dumpTemplateDeclSpecialization(const SpecializationDecl *D, + bool DumpExplicitInst, + bool DumpRefOnly); + template <typename TemplateDecl> + void dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst); // Objective-C utilities. void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams); @@ -294,20 +153,26 @@ namespace { } void VisitVariableArrayType(const VariableArrayType *T) { OS << " "; - dumpSourceRange(T->getBracketsRange()); + NodeDumper.dumpSourceRange(T->getBracketsRange()); VisitArrayType(T); dumpStmt(T->getSizeExpr()); } void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { - VisitArrayType(T); + switch (T->getSizeModifier()) { + case ArrayType::Normal: break; + case ArrayType::Static: OS << " static"; break; + case ArrayType::Star: OS << " *"; break; + } + OS << " " << T->getIndexTypeQualifiers().getAsString(); OS << " "; - dumpSourceRange(T->getBracketsRange()); + NodeDumper.dumpSourceRange(T->getBracketsRange()); + dumpTypeAsChild(T->getElementType()); dumpStmt(T->getSizeExpr()); } void VisitDependentSizedExtVectorType( const DependentSizedExtVectorType *T) { OS << " "; - dumpLocation(T->getAttributeLoc()); + NodeDumper.dumpLocation(T->getAttributeLoc()); dumpTypeAsChild(T->getElementType()); dumpStmt(T->getSizeExpr()); } @@ -334,9 +199,10 @@ namespace { void VisitFunctionProtoType(const FunctionProtoType *T) { auto EPI = T->getExtProtoInfo(); if (EPI.HasTrailingReturn) OS << " trailing_return"; - if (T->isConst()) OS << " const"; - if (T->isVolatile()) OS << " volatile"; - if (T->isRestrict()) OS << " restrict"; + + if (!T->getTypeQuals().empty()) + OS << " " << T->getTypeQuals().getAsString(); + switch (EPI.RefQualifier) { case RQ_None: break; case RQ_LValue: OS << " &"; break; @@ -461,12 +327,6 @@ namespace { void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D); void VisitCXXRecordDecl(const CXXRecordDecl *D); void VisitStaticAssertDecl(const StaticAssertDecl *D); - template<typename SpecializationDecl> - void VisitTemplateDeclSpecialization(const SpecializationDecl *D, - bool DumpExplicitInst, - bool DumpRefOnly); - template<typename TemplateDecl> - void VisitTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst); void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); void VisitClassTemplateDecl(const ClassTemplateDecl *D); void VisitClassTemplateSpecializationDecl( @@ -508,19 +368,22 @@ namespace { void VisitBlockDecl(const BlockDecl *D); // Stmts. - void VisitStmt(const Stmt *Node); void VisitDeclStmt(const DeclStmt *Node); void VisitAttributedStmt(const AttributedStmt *Node); + void VisitIfStmt(const IfStmt *Node); + void VisitSwitchStmt(const SwitchStmt *Node); + void VisitWhileStmt(const WhileStmt *Node); void VisitLabelStmt(const LabelStmt *Node); void VisitGotoStmt(const GotoStmt *Node); void VisitCXXCatchStmt(const CXXCatchStmt *Node); + void VisitCaseStmt(const CaseStmt *Node); void VisitCapturedStmt(const CapturedStmt *Node); // OpenMP void VisitOMPExecutableDirective(const OMPExecutableDirective *Node); // Exprs - void VisitExpr(const Expr *Node); + void VisitCallExpr(const CallExpr *Node); void VisitCastExpr(const CastExpr *Node); void VisitImplicitCastExpr(const ImplicitCastExpr *Node); void VisitDeclRefExpr(const DeclRefExpr *Node); @@ -531,8 +394,6 @@ namespace { void VisitFloatingLiteral(const FloatingLiteral *Node); void VisitStringLiteral(const StringLiteral *Str); void VisitInitListExpr(const InitListExpr *ILE); - void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *ILE); - void VisitArrayInitIndexExpr(const ArrayInitIndexExpr *ILE); void VisitUnaryOperator(const UnaryOperator *Node); void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); void VisitMemberExpr(const MemberExpr *Node); @@ -557,9 +418,7 @@ namespace { void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node); void VisitExprWithCleanups(const ExprWithCleanups *Node); void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node); - void dumpCXXTemporary(const CXXTemporary *Temporary); void VisitLambdaExpr(const LambdaExpr *Node) { - VisitExpr(Node); dumpDecl(Node->getLambdaClass()); } void VisitSizeOfPackExpr(const SizeOfPackExpr *Node); @@ -579,22 +438,7 @@ namespace { void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node); // Comments. - const char *getCommandName(unsigned CommandID); - void dumpComment(const Comment *C); - - // Inline comments. - void visitTextComment(const TextComment *C); - void visitInlineCommandComment(const InlineCommandComment *C); - void visitHTMLStartTagComment(const HTMLStartTagComment *C); - void visitHTMLEndTagComment(const HTMLEndTagComment *C); - - // Block comments. - void visitBlockCommandComment(const BlockCommandComment *C); - void visitParamCommandComment(const ParamCommandComment *C); - void visitTParamCommandComment(const TParamCommandComment *C); - void visitVerbatimBlockComment(const VerbatimBlockComment *C); - void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C); - void visitVerbatimLineComment(const VerbatimLineComment *C); + void dumpComment(const Comment *C, const FullComment *FC); }; } @@ -602,77 +446,6 @@ namespace { // Utilities //===----------------------------------------------------------------------===// -void ASTDumper::dumpPointer(const void *Ptr) { - ColorScope Color(*this, AddressColor); - OS << ' ' << Ptr; -} - -void ASTDumper::dumpLocation(SourceLocation Loc) { - if (!SM) - return; - - ColorScope Color(*this, LocationColor); - SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); - - // The general format we print out is filename:line:col, but we drop pieces - // that haven't changed since the last loc printed. - PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); - - if (PLoc.isInvalid()) { - OS << "<invalid sloc>"; - return; - } - - if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { - OS << PLoc.getFilename() << ':' << PLoc.getLine() - << ':' << PLoc.getColumn(); - LastLocFilename = PLoc.getFilename(); - LastLocLine = PLoc.getLine(); - } else if (PLoc.getLine() != LastLocLine) { - OS << "line" << ':' << PLoc.getLine() - << ':' << PLoc.getColumn(); - LastLocLine = PLoc.getLine(); - } else { - OS << "col" << ':' << PLoc.getColumn(); - } -} - -void ASTDumper::dumpSourceRange(SourceRange R) { - // Can't translate locations if a SourceManager isn't available. - if (!SM) - return; - - OS << " <"; - dumpLocation(R.getBegin()); - if (R.getBegin() != R.getEnd()) { - OS << ", "; - dumpLocation(R.getEnd()); - } - OS << ">"; - - // <t2.c:123:421[blah], t2.c:412:321> - -} - -void ASTDumper::dumpBareType(QualType T, bool Desugar) { - ColorScope Color(*this, TypeColor); - - SplitQualType T_split = T.split(); - OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'"; - - if (Desugar && !T.isNull()) { - // If the type is sugared, also dump a (shallow) desugared type. - SplitQualType D_split = T.getSplitDesugaredType(); - if (T_split != D_split) - OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'"; - } -} - -void ASTDumper::dumpType(QualType T) { - OS << ' '; - dumpBareType(T); -} - void ASTDumper::dumpTypeAsChild(QualType T) { SplitQualType SQT = T.split(); if (!SQT.Quals.hasQualifiers()) @@ -680,9 +453,9 @@ void ASTDumper::dumpTypeAsChild(QualType T) { dumpChild([=] { OS << "QualType"; - dumpPointer(T.getAsOpaquePtr()); + NodeDumper.dumpPointer(T.getAsOpaquePtr()); OS << " "; - dumpBareType(T, false); + NodeDumper.dumpBareType(T, false); OS << " " << T.split().Quals.getAsString(); dumpTypeAsChild(T.split().Ty); }); @@ -691,27 +464,27 @@ void ASTDumper::dumpTypeAsChild(QualType T) { void ASTDumper::dumpTypeAsChild(const Type *T) { dumpChild([=] { if (!T) { - ColorScope Color(*this, NullColor); + ColorScope Color(OS, ShowColors, NullColor); OS << "<<<NULL>>>"; return; } if (const LocInfoType *LIT = llvm::dyn_cast<LocInfoType>(T)) { { - ColorScope Color(*this, TypeColor); + ColorScope Color(OS, ShowColors, TypeColor); OS << "LocInfo Type"; } - dumpPointer(T); + NodeDumper.dumpPointer(T); dumpTypeAsChild(LIT->getTypeSourceInfo()->getType()); return; } { - ColorScope Color(*this, TypeColor); + ColorScope Color(OS, ShowColors, TypeColor); OS << T->getTypeClassName() << "Type"; } - dumpPointer(T); + NodeDumper.dumpPointer(T); OS << " "; - dumpBareType(QualType(T, 0), false); + NodeDumper.dumpBareType(QualType(T, 0), false); QualType SingleStepDesugar = T->getLocallyUnqualifiedSingleStepDesugaredType(); @@ -735,28 +508,6 @@ void ASTDumper::dumpTypeAsChild(const Type *T) { }); } -void ASTDumper::dumpBareDeclRef(const Decl *D) { - if (!D) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>>"; - return; - } - - { - ColorScope Color(*this, DeclKindNameColor); - OS << D->getDeclKindName(); - } - dumpPointer(D); - - if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { - ColorScope Color(*this, DeclNameColor); - OS << " '" << ND->getDeclName() << '\''; - } - - if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) - dumpType(VD->getType()); -} - void ASTDumper::dumpDeclRef(const Decl *D, const char *Label) { if (!D) return; @@ -768,22 +519,6 @@ void ASTDumper::dumpDeclRef(const Decl *D, const char *Label) { }); } -void ASTDumper::dumpName(const NamedDecl *ND) { - if (ND->getDeclName()) { - ColorScope Color(*this, DeclNameColor); - OS << ' ' << ND->getNameAsString(); - } -} - -bool ASTDumper::hasNodes(const DeclContext *DC) { - if (!DC) - return false; - - return DC->hasExternalLexicalStorage() || - (Deserialize ? DC->decls_begin() != DC->decls_end() - : DC->noload_decls_begin() != DC->noload_decls_end()); -} - void ASTDumper::dumpDeclContext(const DeclContext *DC) { if (!DC) return; @@ -792,8 +527,8 @@ void ASTDumper::dumpDeclContext(const DeclContext *DC) { dumpDecl(D); if (DC->hasExternalLexicalStorage()) { - dumpChild([=]{ - ColorScope Color(*this, UndeserializedColor); + dumpChild([=] { + ColorScope Color(OS, ShowColors, UndeserializedColor); OS << "<undeserialized declarations>"; }); } @@ -802,12 +537,12 @@ void ASTDumper::dumpDeclContext(const DeclContext *DC) { void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { dumpChild([=] { OS << "StoredDeclsMap "; - dumpBareDeclRef(cast<Decl>(DC)); + NodeDumper.dumpBareDeclRef(cast<Decl>(DC)); const DeclContext *Primary = DC->getPrimaryContext(); if (Primary != DC) { OS << " primary"; - dumpPointer(cast<Decl>(Primary)); + NodeDumper.dumpPointer(cast<Decl>(Primary)); } bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage(); @@ -822,14 +557,14 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { dumpChild([=] { OS << "DeclarationName "; { - ColorScope Color(*this, DeclNameColor); + ColorScope Color(OS, ShowColors, DeclNameColor); OS << '\'' << Name << '\''; } for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI) { dumpChild([=] { - dumpBareDeclRef(*RI); + NodeDumper.dumpBareDeclRef(*RI); if ((*RI)->isHidden()) OS << " hidden"; @@ -851,7 +586,7 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { if (HasUndeserializedLookups) { dumpChild([=] { - ColorScope Color(*this, UndeserializedColor); + ColorScope Color(OS, ShowColors, UndeserializedColor); OS << "<undeserialized lookups>"; }); } @@ -861,7 +596,7 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { void ASTDumper::dumpAttr(const Attr *A) { dumpChild([=] { { - ColorScope Color(*this, AttrColor); + ColorScope Color(OS, ShowColors, AttrColor); switch (A->getKind()) { #define ATTR(X) case attr::X: OS << #X; break; @@ -869,8 +604,8 @@ void ASTDumper::dumpAttr(const Attr *A) { } OS << "Attr"; } - dumpPointer(A); - dumpSourceRange(A->getRange()); + NodeDumper.dumpPointer(A); + NodeDumper.dumpSourceRange(A->getRange()); if (A->isInherited()) OS << " Inherited"; if (A->isImplicit()) @@ -912,32 +647,16 @@ static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) { // C++ Utilities //===----------------------------------------------------------------------===// -void ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) { - switch (AS) { - case AS_none: - break; - case AS_public: - OS << "public"; - break; - case AS_protected: - OS << "protected"; - break; - case AS_private: - OS << "private"; - break; - } -} - void ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) { dumpChild([=] { OS << "CXXCtorInitializer"; if (Init->isAnyMemberInitializer()) { OS << ' '; - dumpBareDeclRef(Init->getAnyMember()); + NodeDumper.dumpBareDeclRef(Init->getAnyMember()); } else if (Init->isBaseInitializer()) { - dumpType(QualType(Init->getBaseClass(), 0)); + NodeDumper.dumpType(QualType(Init->getBaseClass(), 0)); } else if (Init->isDelegatingInitializer()) { - dumpType(Init->getTypeSourceInfo()->getType()); + NodeDumper.dumpType(Init->getTypeSourceInfo()->getType()); } else { llvm_unreachable("Unknown initializer type"); } @@ -960,8 +679,9 @@ void ASTDumper::dumpTemplateArgumentListInfo( dumpTemplateArgumentLoc(TALI[i]); } -void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) { - dumpTemplateArgument(A.getArgument(), A.getSourceRange()); +void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A, + const Decl *From, const char *Label) { + dumpTemplateArgument(A.getArgument(), A.getSourceRange(), From, Label); } void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) { @@ -969,11 +689,15 @@ void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) { dumpTemplateArgument(TAL[i]); } -void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { +void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R, + const Decl *From, const char *Label) { dumpChild([=] { OS << "TemplateArgument"; if (R.isValid()) - dumpSourceRange(R); + NodeDumper.dumpSourceRange(R); + + if (From) + dumpDeclRef(From, Label); switch (A.getKind()) { case TemplateArgument::Null: @@ -981,7 +705,7 @@ void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { break; case TemplateArgument::Type: OS << " type"; - dumpType(A.getAsType()); + NodeDumper.dumpType(A.getAsType()); break; case TemplateArgument::Declaration: OS << " decl"; @@ -1034,22 +758,22 @@ void ASTDumper::dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) { void ASTDumper::dumpDecl(const Decl *D) { dumpChild([=] { if (!D) { - ColorScope Color(*this, NullColor); + ColorScope Color(OS, ShowColors, NullColor); OS << "<<<NULL>>>"; return; } { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << D->getDeclKindName() << "Decl"; } - dumpPointer(D); + NodeDumper.dumpPointer(D); if (D->getLexicalDeclContext() != D->getDeclContext()) OS << " parent " << cast<Decl>(D->getDeclContext()); dumpPreviousDecl(OS, D); - dumpSourceRange(D->getSourceRange()); + NodeDumper.dumpSourceRange(D->getSourceRange()); OS << ' '; - dumpLocation(D->getLocation()); + NodeDumper.dumpLocation(D->getLocation()); if (D->isFromASTFile()) OS << " imported"; if (Module *M = D->getOwningModule()) @@ -1082,22 +806,25 @@ void ASTDumper::dumpDecl(const Decl *D) { if (const FullComment *Comment = D->getASTContext().getLocalCommentForDeclUncached(D)) - dumpFullComment(Comment); + dumpComment(Comment, Comment); // Decls within functions are visited by the body. - if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) && - hasNodes(dyn_cast<DeclContext>(D))) - dumpDeclContext(cast<DeclContext>(D)); + if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D)) { + auto DC = dyn_cast<DeclContext>(D); + if (DC && + (DC->hasExternalLexicalStorage() || + (Deserialize ? DC->decls_begin() != DC->decls_end() + : DC->noload_decls_begin() != DC->noload_decls_end()))) + dumpDeclContext(DC); + } }); } -void ASTDumper::VisitLabelDecl(const LabelDecl *D) { - dumpName(D); -} +void ASTDumper::VisitLabelDecl(const LabelDecl *D) { NodeDumper.dumpName(D); } void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) { - dumpName(D); - dumpType(D->getUnderlyingType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getUnderlyingType()); if (D->isModulePrivate()) OS << " __module_private__"; dumpTypeAsChild(D->getUnderlyingType()); @@ -1110,16 +837,16 @@ void ASTDumper::VisitEnumDecl(const EnumDecl *D) { else OS << " struct"; } - dumpName(D); + NodeDumper.dumpName(D); if (D->isModulePrivate()) OS << " __module_private__"; if (D->isFixed()) - dumpType(D->getIntegerType()); + NodeDumper.dumpType(D->getIntegerType()); } void ASTDumper::VisitRecordDecl(const RecordDecl *D) { OS << ' ' << D->getKindName(); - dumpName(D); + NodeDumper.dumpName(D); if (D->isModulePrivate()) OS << " __module_private__"; if (D->isCompleteDefinition()) @@ -1127,23 +854,23 @@ void ASTDumper::VisitRecordDecl(const RecordDecl *D) { } void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); if (const Expr *Init = D->getInitExpr()) dumpStmt(Init); } void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); for (auto *Child : D->chain()) dumpDeclRef(Child); } void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); StorageClass SC = D->getStorageClass(); if (SC != SC_None) @@ -1224,8 +951,8 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { } void ASTDumper::VisitFieldDecl(const FieldDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); if (D->isMutable()) OS << " mutable"; if (D->isModulePrivate()) @@ -1238,8 +965,8 @@ void ASTDumper::VisitFieldDecl(const FieldDecl *D) { } void ASTDumper::VisitVarDecl(const VarDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); StorageClass SC = D->getStorageClass(); if (SC != SC_None) OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); @@ -1273,8 +1000,8 @@ void ASTDumper::VisitDecompositionDecl(const DecompositionDecl *D) { } void ASTDumper::VisitBindingDecl(const BindingDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); if (auto *E = D->getBinding()) dumpStmt(E); } @@ -1321,12 +1048,13 @@ void ASTDumper::VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { } void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); OS << " combiner"; - dumpStmt(D->getCombiner()); - if (auto *Initializer = D->getInitializer()) { + NodeDumper.dumpPointer(D->getCombiner()); + if (const auto *Initializer = D->getInitializer()) { OS << " initializer"; + NodeDumper.dumpPointer(Initializer); switch (D->getInitializerKind()) { case OMPDeclareReductionDecl::DirectInit: OS << " omp_priv = "; @@ -1337,33 +1065,36 @@ void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { case OMPDeclareReductionDecl::CallInit: break; } - dumpStmt(Initializer); } + + dumpStmt(D->getCombiner()); + if (const auto *Initializer = D->getInitializer()) + dumpStmt(Initializer); } void ASTDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) { for (auto *C : D->clauselists()) { dumpChild([=] { if (!C) { - ColorScope Color(*this, NullColor); + ColorScope Color(OS, ShowColors, NullColor); OS << "<<<NULL>>> OMPClause"; return; } { - ColorScope Color(*this, AttrColor); + ColorScope Color(OS, ShowColors, AttrColor); StringRef ClauseName(getOpenMPClauseName(C->getClauseKind())); OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper() << ClauseName.drop_front() << "Clause"; } - dumpPointer(C); - dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc())); + NodeDumper.dumpPointer(C); + NodeDumper.dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc())); }); } } void ASTDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); dumpStmt(D->getInit()); } @@ -1372,7 +1103,7 @@ void ASTDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { //===----------------------------------------------------------------------===// void ASTDumper::VisitNamespaceDecl(const NamespaceDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); if (D->isInline()) OS << " inline"; if (!D->isOriginalNamespace()) @@ -1381,22 +1112,22 @@ void ASTDumper::VisitNamespaceDecl(const NamespaceDecl *D) { void ASTDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { OS << ' '; - dumpBareDeclRef(D->getNominatedNamespace()); + NodeDumper.dumpBareDeclRef(D->getNominatedNamespace()); } void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); dumpDeclRef(D->getAliasedNamespace()); } void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { - dumpName(D); - dumpType(D->getUnderlyingType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getUnderlyingType()); dumpTypeAsChild(D->getUnderlyingType()); } void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); dumpDecl(D->getTemplatedDecl()); } @@ -1408,7 +1139,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "DefinitionData"; } #define FLAG(fn, name) if (D->fn()) OS << " " #name; @@ -1436,7 +1167,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "DefaultConstructor"; } FLAG(hasDefaultConstructor, exists); @@ -1450,7 +1181,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "CopyConstructor"; } FLAG(hasSimpleCopyConstructor, simple); @@ -1468,7 +1199,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "MoveConstructor"; } FLAG(hasMoveConstructor, exists); @@ -1485,7 +1216,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "CopyAssignment"; } FLAG(hasTrivialCopyAssignment, trivial); @@ -1499,7 +1230,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "MoveAssignment"; } FLAG(hasMoveAssignment, exists); @@ -1513,7 +1244,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "Destructor"; } FLAG(hasSimpleDestructor, simple); @@ -1532,8 +1263,8 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { if (I.isVirtual()) OS << "virtual "; - dumpAccessSpecifier(I.getAccessSpecifier()); - dumpType(I.getType()); + NodeDumper.dumpAccessSpecifier(I.getAccessSpecifier()); + NodeDumper.dumpType(I.getType()); if (I.isPackExpansion()) OS << "..."; }); @@ -1545,10 +1276,10 @@ void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) { dumpStmt(D->getMessage()); } -template<typename SpecializationDecl> -void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D, - bool DumpExplicitInst, - bool DumpRefOnly) { +template <typename SpecializationDecl> +void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D, + bool DumpExplicitInst, + bool DumpRefOnly) { bool DumpedAny = false; for (auto *RedeclWithBadType : D->redecls()) { // FIXME: The redecls() range sometimes has elements of a less-specific @@ -1587,28 +1318,27 @@ void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D, dumpDeclRef(D); } -template<typename TemplateDecl> -void ASTDumper::VisitTemplateDecl(const TemplateDecl *D, - bool DumpExplicitInst) { - dumpName(D); +template <typename TemplateDecl> +void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) { + NodeDumper.dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); dumpDecl(D->getTemplatedDecl()); for (auto *Child : D->specializations()) - VisitTemplateDeclSpecialization(Child, DumpExplicitInst, - !D->isCanonicalDecl()); + dumpTemplateDeclSpecialization(Child, DumpExplicitInst, + !D->isCanonicalDecl()); } void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { // FIXME: We don't add a declaration of a function template specialization // to its context when it's explicitly instantiated, so dump explicit // instantiations when we dump the template itself. - VisitTemplateDecl(D, true); + dumpTemplateDecl(D, true); } void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { - VisitTemplateDecl(D, false); + dumpTemplateDecl(D, false); } void ASTDumper::VisitClassTemplateSpecializationDecl( @@ -1631,11 +1361,11 @@ void ASTDumper::VisitClassScopeFunctionSpecializationDecl( } void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { - VisitTemplateDecl(D, false); + dumpTemplateDecl(D, false); } void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); } @@ -1659,25 +1389,25 @@ void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { OS << " depth " << D->getDepth() << " index " << D->getIndex(); if (D->isParameterPack()) OS << " ..."; - dumpName(D); + NodeDumper.dumpName(D); if (D->hasDefaultArgument()) - dumpTemplateArgument(D->getDefaultArgument()); - if (auto *From = D->getDefaultArgStorage().getInheritedFrom()) - dumpDeclRef(From, D->defaultArgumentWasInherited() ? "inherited from" - : "previous"); + dumpTemplateArgument(D->getDefaultArgument(), SourceRange(), + D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" + : "previous"); } void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { - dumpType(D->getType()); + NodeDumper.dumpType(D->getType()); OS << " depth " << D->getDepth() << " index " << D->getIndex(); if (D->isParameterPack()) OS << " ..."; - dumpName(D); + NodeDumper.dumpName(D); if (D->hasDefaultArgument()) - dumpTemplateArgument(D->getDefaultArgument()); - if (auto *From = D->getDefaultArgStorage().getInheritedFrom()) - dumpDeclRef(From, D->defaultArgumentWasInherited() ? "inherited from" - : "previous"); + dumpTemplateArgument(D->getDefaultArgument(), SourceRange(), + D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" + : "previous"); } void ASTDumper::VisitTemplateTemplateParmDecl( @@ -1685,13 +1415,12 @@ void ASTDumper::VisitTemplateTemplateParmDecl( OS << " depth " << D->getDepth() << " index " << D->getIndex(); if (D->isParameterPack()) OS << " ..."; - dumpName(D); + NodeDumper.dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); if (D->hasDefaultArgument()) - dumpTemplateArgumentLoc(D->getDefaultArgument()); - if (auto *From = D->getDefaultArgStorage().getInheritedFrom()) - dumpDeclRef(From, D->defaultArgumentWasInherited() ? "inherited from" - : "previous"); + dumpTemplateArgumentLoc( + D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); } void ASTDumper::VisitUsingDecl(const UsingDecl *D) { @@ -1714,12 +1443,12 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) if (D->getQualifier()) D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); OS << D->getNameAsString(); - dumpType(D->getType()); + NodeDumper.dumpType(D->getType()); } void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { OS << ' '; - dumpBareDeclRef(D->getTargetDecl()); + NodeDumper.dumpBareDeclRef(D->getTargetDecl()); if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) dumpTypeAsChild(TD->getTypeForDecl()); } @@ -1731,21 +1460,21 @@ void ASTDumper::VisitConstructorUsingShadowDecl( dumpChild([=] { OS << "target "; - dumpBareDeclRef(D->getTargetDecl()); + NodeDumper.dumpBareDeclRef(D->getTargetDecl()); }); dumpChild([=] { OS << "nominated "; - dumpBareDeclRef(D->getNominatedBaseClass()); + NodeDumper.dumpBareDeclRef(D->getNominatedBaseClass()); OS << ' '; - dumpBareDeclRef(D->getNominatedBaseClassShadowDecl()); + NodeDumper.dumpBareDeclRef(D->getNominatedBaseClassShadowDecl()); }); dumpChild([=] { OS << "constructed "; - dumpBareDeclRef(D->getConstructedBaseClass()); + NodeDumper.dumpBareDeclRef(D->getConstructedBaseClass()); OS << ' '; - dumpBareDeclRef(D->getConstructedBaseClassShadowDecl()); + NodeDumper.dumpBareDeclRef(D->getConstructedBaseClassShadowDecl()); }); } @@ -1758,12 +1487,12 @@ void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { void ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) { OS << ' '; - dumpAccessSpecifier(D->getAccess()); + NodeDumper.dumpAccessSpecifier(D->getAccess()); } void ASTDumper::VisitFriendDecl(const FriendDecl *D) { if (TypeSourceInfo *T = D->getFriendType()) - dumpType(T->getType()); + NodeDumper.dumpType(T->getType()); else dumpDecl(D->getFriendDecl()); } @@ -1773,8 +1502,8 @@ void ASTDumper::VisitFriendDecl(const FriendDecl *D) { //===----------------------------------------------------------------------===// void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); if (D->getSynthesize()) OS << " synthesize"; @@ -1802,8 +1531,8 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { OS << " -"; else OS << " +"; - dumpName(D); - dumpType(D->getReturnType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getReturnType()); if (D->isThisDeclarationADefinition()) { dumpDeclContext(D); @@ -1820,7 +1549,7 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { } void ASTDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); switch (D->getVariance()) { case ObjCTypeParamVariance::Invariant: break; @@ -1836,11 +1565,11 @@ void ASTDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) { if (D->hasExplicitBound()) OS << " bounded"; - dumpType(D->getUnderlyingType()); + NodeDumper.dumpType(D->getUnderlyingType()); } void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); dumpDeclRef(D->getClassInterface()); dumpObjCTypeParamList(D->getTypeParamList()); dumpDeclRef(D->getImplementation()); @@ -1851,20 +1580,20 @@ void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { } void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); dumpDeclRef(D->getClassInterface()); dumpDeclRef(D->getCategoryDecl()); } void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); for (auto *Child : D->protocols()) dumpDeclRef(Child); } void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); dumpObjCTypeParamList(D->getTypeParamListAsWritten()); dumpDeclRef(D->getSuperClass(), "super"); @@ -1874,7 +1603,7 @@ void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { } void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); dumpDeclRef(D->getSuperClass(), "super"); dumpDeclRef(D->getClassInterface()); for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(), @@ -1884,13 +1613,13 @@ void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { } void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); dumpDeclRef(D->getClassInterface()); } void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { - dumpName(D); - dumpType(D->getType()); + NodeDumper.dumpName(D); + NodeDumper.dumpType(D->getType()); if (D->getPropertyImplementation() == ObjCPropertyDecl::Required) OS << " required"; @@ -1929,7 +1658,7 @@ void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { } void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { - dumpName(D->getPropertyDecl()); + NodeDumper.dumpName(D->getPropertyDecl()); if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) OS << " synthesize"; else @@ -1957,7 +1686,7 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) { OS << " nested"; if (I.getVariable()) { OS << ' '; - dumpBareDeclRef(I.getVariable()); + NodeDumper.dumpBareDeclRef(I.getVariable()); } if (I.hasCopyExpr()) dumpStmt(I.getCopyExpr()); @@ -1973,39 +1702,68 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) { void ASTDumper::dumpStmt(const Stmt *S) { dumpChild([=] { if (!S) { - ColorScope Color(*this, NullColor); + ColorScope Color(OS, ShowColors, NullColor); OS << "<<<NULL>>>"; return; } - - // Some statements have custom mechanisms for dumping their children. - if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { - VisitDeclStmt(DS); - return; + { + ColorScope Color(OS, ShowColors, StmtColor); + OS << S->getStmtClassName(); } - if (const GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(S)) { - VisitGenericSelectionExpr(GSE); - return; + NodeDumper.dumpPointer(S); + NodeDumper.dumpSourceRange(S->getSourceRange()); + + if (const auto *E = dyn_cast<Expr>(S)) { + NodeDumper.dumpType(E->getType()); + + { + ColorScope Color(OS, ShowColors, ValueKindColor); + switch (E->getValueKind()) { + case VK_RValue: + break; + case VK_LValue: + OS << " lvalue"; + break; + case VK_XValue: + OS << " xvalue"; + break; + } + } + + { + ColorScope Color(OS, ShowColors, ObjectKindColor); + switch (E->getObjectKind()) { + case OK_Ordinary: + break; + case OK_BitField: + OS << " bitfield"; + break; + case OK_ObjCProperty: + OS << " objcproperty"; + break; + case OK_ObjCSubscript: + OS << " objcsubscript"; + break; + case OK_VectorComponent: + OS << " vectorcomponent"; + break; + } + } } ConstStmtVisitor<ASTDumper>::Visit(S); + // Some statements have custom mechanisms for dumping their children. + if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S)) { + return; + } + for (const Stmt *SubStmt : S->children()) dumpStmt(SubStmt); }); } -void ASTDumper::VisitStmt(const Stmt *Node) { - { - ColorScope Color(*this, StmtColor); - OS << Node->getStmtClassName(); - } - dumpPointer(Node); - dumpSourceRange(Node->getSourceRange()); -} - void ASTDumper::VisitDeclStmt(const DeclStmt *Node) { - VisitStmt(Node); for (DeclStmt::const_decl_iterator I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) @@ -2013,31 +1771,52 @@ void ASTDumper::VisitDeclStmt(const DeclStmt *Node) { } void ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) { - VisitStmt(Node); for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(), E = Node->getAttrs().end(); I != E; ++I) dumpAttr(*I); } +void ASTDumper::VisitIfStmt(const IfStmt *Node) { + if (Node->hasInitStorage()) + OS << " has_init"; + if (Node->hasVarStorage()) + OS << " has_var"; + if (Node->hasElseStorage()) + OS << " has_else"; +} + +void ASTDumper::VisitSwitchStmt(const SwitchStmt *Node) { + if (Node->hasInitStorage()) + OS << " has_init"; + if (Node->hasVarStorage()) + OS << " has_var"; +} + +void ASTDumper::VisitWhileStmt(const WhileStmt *Node) { + if (Node->hasVarStorage()) + OS << " has_var"; +} + void ASTDumper::VisitLabelStmt(const LabelStmt *Node) { - VisitStmt(Node); OS << " '" << Node->getName() << "'"; } void ASTDumper::VisitGotoStmt(const GotoStmt *Node) { - VisitStmt(Node); OS << " '" << Node->getLabel()->getName() << "'"; - dumpPointer(Node->getLabel()); + NodeDumper.dumpPointer(Node->getLabel()); } void ASTDumper::VisitCXXCatchStmt(const CXXCatchStmt *Node) { - VisitStmt(Node); dumpDecl(Node->getExceptionDecl()); } +void ASTDumper::VisitCaseStmt(const CaseStmt *Node) { + if (Node->caseStmtIsGNURange()) + OS << " gnu_range"; +} + void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) { - VisitStmt(Node); dumpDecl(Node->getCapturedDecl()); } @@ -2047,22 +1826,21 @@ void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) { void ASTDumper::VisitOMPExecutableDirective( const OMPExecutableDirective *Node) { - VisitStmt(Node); for (auto *C : Node->clauses()) { dumpChild([=] { if (!C) { - ColorScope Color(*this, NullColor); + ColorScope Color(OS, ShowColors, NullColor); OS << "<<<NULL>>> OMPClause"; return; } { - ColorScope Color(*this, AttrColor); + ColorScope Color(OS, ShowColors, AttrColor); StringRef ClauseName(getOpenMPClauseName(C->getClauseKind())); OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper() << ClauseName.drop_front() << "Clause"; } - dumpPointer(C); - dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc())); + NodeDumper.dumpPointer(C); + NodeDumper.dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc())); if (C->isImplicit()) OS << " <implicit>"; for (auto *S : C->children()) @@ -2075,45 +1853,6 @@ void ASTDumper::VisitOMPExecutableDirective( // Expr dumping methods. //===----------------------------------------------------------------------===// -void ASTDumper::VisitExpr(const Expr *Node) { - VisitStmt(Node); - dumpType(Node->getType()); - - { - ColorScope Color(*this, ValueKindColor); - switch (Node->getValueKind()) { - case VK_RValue: - break; - case VK_LValue: - OS << " lvalue"; - break; - case VK_XValue: - OS << " xvalue"; - break; - } - } - - { - ColorScope Color(*this, ObjectKindColor); - switch (Node->getObjectKind()) { - case OK_Ordinary: - break; - case OK_BitField: - OS << " bitfield"; - break; - case OK_ObjCProperty: - OS << " objcproperty"; - break; - case OK_ObjCSubscript: - OS << " objcsubscript"; - break; - case OK_VectorComponent: - OS << " vectorcomponent"; - break; - } - } -} - static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { if (Node->path_empty()) return; @@ -2139,11 +1878,15 @@ static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { OS << ')'; } +void ASTDumper::VisitCallExpr(const CallExpr *Node) { + if (Node->usesADL()) + OS << " adl"; +} + void ASTDumper::VisitCastExpr(const CastExpr *Node) { - VisitExpr(Node); OS << " <"; { - ColorScope Color(*this, CastColor); + ColorScope Color(OS, ShowColors, CastColor); OS << Node->getCastKindName(); } dumpBasePath(OS, Node); @@ -2157,19 +1900,16 @@ void ASTDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) { } void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { - VisitExpr(Node); - OS << " "; - dumpBareDeclRef(Node->getDecl()); + NodeDumper.dumpBareDeclRef(Node->getDecl()); if (Node->getDecl() != Node->getFoundDecl()) { OS << " ("; - dumpBareDeclRef(Node->getFoundDecl()); + NodeDumper.dumpBareDeclRef(Node->getFoundDecl()); OS << ")"; } } void ASTDumper::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node) { - VisitExpr(Node); OS << " ("; if (!Node->requiresADL()) OS << "no "; @@ -2180,85 +1920,65 @@ void ASTDumper::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node) { if (I == E) OS << " empty"; for (; I != E; ++I) - dumpPointer(*I); + NodeDumper.dumpPointer(*I); } void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { - VisitExpr(Node); - { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << " " << Node->getDecl()->getDeclKindName() << "Decl"; } OS << "='" << *Node->getDecl() << "'"; - dumpPointer(Node->getDecl()); + NodeDumper.dumpPointer(Node->getDecl()); if (Node->isFreeIvar()) OS << " isFreeIvar"; } void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { - VisitExpr(Node); - OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType()); + OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind()); } void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { - VisitExpr(Node); - ColorScope Color(*this, ValueColor); + ColorScope Color(OS, ShowColors, ValueColor); OS << " " << Node->getValue(); } void ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) { - VisitExpr(Node); - bool isSigned = Node->getType()->isSignedIntegerType(); - ColorScope Color(*this, ValueColor); + ColorScope Color(OS, ShowColors, ValueColor); OS << " " << Node->getValue().toString(10, isSigned); } void ASTDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) { - VisitExpr(Node); - - ColorScope Color(*this, ValueColor); + ColorScope Color(OS, ShowColors, ValueColor); OS << " " << Node->getValueAsString(/*Radix=*/10); } void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) { - VisitExpr(Node); - ColorScope Color(*this, ValueColor); + ColorScope Color(OS, ShowColors, ValueColor); OS << " " << Node->getValueAsApproximateDouble(); } void ASTDumper::VisitStringLiteral(const StringLiteral *Str) { - VisitExpr(Str); - ColorScope Color(*this, ValueColor); + ColorScope Color(OS, ShowColors, ValueColor); OS << " "; Str->outputString(OS); } void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) { - VisitExpr(ILE); + if (auto *Field = ILE->getInitializedFieldInUnion()) { + OS << " field "; + NodeDumper.dumpBareDeclRef(Field); + } if (auto *Filler = ILE->getArrayFiller()) { dumpChild([=] { OS << "array filler"; dumpStmt(Filler); }); } - if (auto *Field = ILE->getInitializedFieldInUnion()) { - OS << " field "; - dumpBareDeclRef(Field); - } -} - -void ASTDumper::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { - VisitExpr(E); -} - -void ASTDumper::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) { - VisitExpr(E); } void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { - VisitExpr(Node); OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; if (!Node->canOverflow()) @@ -2267,7 +1987,6 @@ void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { void ASTDumper::VisitUnaryExprOrTypeTraitExpr( const UnaryExprOrTypeTraitExpr *Node) { - VisitExpr(Node); switch(Node->getKind()) { case UETT_SizeOf: OS << " sizeof"; @@ -2281,51 +2000,46 @@ void ASTDumper::VisitUnaryExprOrTypeTraitExpr( case UETT_OpenMPRequiredSimdAlign: OS << " __builtin_omp_required_simd_align"; break; + case UETT_PreferredAlignOf: + OS << " __alignof"; + break; } if (Node->isArgumentType()) - dumpType(Node->getArgumentType()); + NodeDumper.dumpType(Node->getArgumentType()); } void ASTDumper::VisitMemberExpr(const MemberExpr *Node) { - VisitExpr(Node); OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl(); - dumpPointer(Node->getMemberDecl()); + NodeDumper.dumpPointer(Node->getMemberDecl()); } void ASTDumper::VisitExtVectorElementExpr(const ExtVectorElementExpr *Node) { - VisitExpr(Node); OS << " " << Node->getAccessor().getNameStart(); } void ASTDumper::VisitBinaryOperator(const BinaryOperator *Node) { - VisitExpr(Node); OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; } void ASTDumper::VisitCompoundAssignOperator( const CompoundAssignOperator *Node) { - VisitExpr(Node); OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "' ComputeLHSTy="; - dumpBareType(Node->getComputationLHSType()); + NodeDumper.dumpBareType(Node->getComputationLHSType()); OS << " ComputeResultTy="; - dumpBareType(Node->getComputationResultType()); + NodeDumper.dumpBareType(Node->getComputationResultType()); } void ASTDumper::VisitBlockExpr(const BlockExpr *Node) { - VisitExpr(Node); dumpDecl(Node->getBlockDecl()); } void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { - VisitExpr(Node); - if (Expr *Source = Node->getSourceExpr()) dumpStmt(Source); } void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) { - VisitExpr(E); if (E->isResultDependent()) OS << " result_dependent"; dumpStmt(E->getControllingExpr()); @@ -2335,7 +2049,7 @@ void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) { dumpChild([=] { if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I)) { OS << "case "; - dumpType(TSI->getType()); + NodeDumper.dumpType(TSI->getType()); } else { OS << "default"; } @@ -2353,9 +2067,8 @@ void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) { // GNU extensions. void ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { - VisitExpr(Node); OS << " " << Node->getLabel()->getName(); - dumpPointer(Node->getLabel()); + NodeDumper.dumpPointer(Node->getLabel()); } //===----------------------------------------------------------------------===// @@ -2363,7 +2076,6 @@ void ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { //===----------------------------------------------------------------------===// void ASTDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) { - VisitExpr(Node); OS << " " << Node->getCastName() << "<" << Node->getTypeAsWritten().getAsString() << ">" << " <" << Node->getCastKindName(); @@ -2372,33 +2084,28 @@ void ASTDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) { } void ASTDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) { - VisitExpr(Node); OS << " " << (Node->getValue() ? "true" : "false"); } void ASTDumper::VisitCXXThisExpr(const CXXThisExpr *Node) { - VisitExpr(Node); OS << " this"; } void ASTDumper::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node) { - VisitExpr(Node); OS << " functional cast to " << Node->getTypeAsWritten().getAsString() << " <" << Node->getCastKindName() << ">"; } void ASTDumper::VisitCXXUnresolvedConstructExpr( const CXXUnresolvedConstructExpr *Node) { - VisitExpr(Node); - dumpType(Node->getTypeAsWritten()); + NodeDumper.dumpType(Node->getTypeAsWritten()); if (Node->isListInitialization()) OS << " list"; } void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { - VisitExpr(Node); CXXConstructorDecl *Ctor = Node->getConstructor(); - dumpType(Ctor->getType()); + NodeDumper.dumpType(Ctor->getType()); if (Node->isElidable()) OS << " elidable"; if (Node->isListInitialization()) @@ -2410,62 +2117,50 @@ void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { } void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) { - VisitExpr(Node); OS << " "; - dumpCXXTemporary(Node->getTemporary()); + NodeDumper.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()); + NodeDumper.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()); + NodeDumper.dumpBareDeclRef(Node->getOperatorDelete()); } } void ASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) { - VisitExpr(Node); if (const ValueDecl *VD = Node->getExtendingDecl()) { OS << " extended by "; - dumpBareDeclRef(VD); + NodeDumper.dumpBareDeclRef(VD); } } void ASTDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) { - VisitExpr(Node); for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) dumpDeclRef(Node->getObject(i), "cleanup"); } -void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) { - OS << "(CXXTemporary"; - dumpPointer(Temporary); - OS << ")"; -} - void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { - VisitExpr(Node); - dumpPointer(Node->getPack()); - dumpName(Node->getPack()); + NodeDumper.dumpPointer(Node->getPack()); + NodeDumper.dumpName(Node->getPack()); if (Node->isPartiallySubstituted()) for (const auto &A : Node->getPartialArguments()) dumpTemplateArgument(A); @@ -2473,7 +2168,6 @@ void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { void ASTDumper::VisitCXXDependentScopeMemberExpr( const CXXDependentScopeMemberExpr *Node) { - VisitExpr(Node); OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember(); } @@ -2482,7 +2176,6 @@ void ASTDumper::VisitCXXDependentScopeMemberExpr( //===----------------------------------------------------------------------===// void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { - VisitExpr(Node); OS << " selector="; Node->getSelector().print(OS); switch (Node->getReceiverKind()) { @@ -2491,7 +2184,7 @@ void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { case ObjCMessageExpr::Class: OS << " class="; - dumpBareType(Node->getClassReceiver()); + NodeDumper.dumpBareType(Node->getClassReceiver()); break; case ObjCMessageExpr::SuperInstance: @@ -2505,7 +2198,6 @@ void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { } void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { - VisitExpr(Node); if (auto *BoxingMethod = Node->getBoxingMethod()) { OS << " selector="; BoxingMethod->getSelector().print(OS); @@ -2513,7 +2205,6 @@ void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { } void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { - VisitStmt(Node); if (const VarDecl *CatchParam = Node->getCatchParamDecl()) dumpDecl(CatchParam); else @@ -2521,25 +2212,19 @@ void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { } void ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) { - VisitExpr(Node); - dumpType(Node->getEncodedType()); + NodeDumper.dumpType(Node->getEncodedType()); } void ASTDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) { - VisitExpr(Node); - OS << " "; Node->getSelector().print(OS); } void ASTDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) { - VisitExpr(Node); - OS << ' ' << *Node->getProtocol(); } void ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) { - VisitExpr(Node); if (Node->isImplicitProperty()) { OS << " Kind=MethodRef Getter=\""; if (Node->getImplicitPropertyGetter()) @@ -2570,7 +2255,6 @@ void ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) { } void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { - VisitExpr(Node); if (Node->isArraySubscriptRefExpr()) OS << " Kind=ArraySubscript GetterForArray=\""; else @@ -2591,7 +2275,6 @@ void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { } void ASTDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) { - VisitExpr(Node); OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); } @@ -2599,145 +2282,19 @@ void ASTDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) { // Comments //===----------------------------------------------------------------------===// -const char *ASTDumper::getCommandName(unsigned CommandID) { - if (Traits) - return Traits->getCommandInfo(CommandID)->Name; - const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID); - if (Info) - return Info->Name; - return "<not a builtin command>"; -} - -void ASTDumper::dumpFullComment(const FullComment *C) { - if (!C) - return; - - FC = C; - dumpComment(C); - FC = nullptr; -} - -void ASTDumper::dumpComment(const Comment *C) { +void ASTDumper::dumpComment(const Comment *C, const FullComment *FC) { dumpChild([=] { + NodeDumper.Visit(C, FC); if (!C) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>>"; return; } - - { - ColorScope Color(*this, CommentColor); - OS << C->getCommentKindName(); - } - dumpPointer(C); - dumpSourceRange(C->getSourceRange()); - ConstCommentVisitor<ASTDumper>::visit(C); + ConstCommentVisitor<ASTDumper, void, const FullComment *>::visit(C, FC); for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); I != E; ++I) - dumpComment(*I); + dumpComment(*I, FC); }); } -void ASTDumper::visitTextComment(const TextComment *C) { - OS << " Text=\"" << C->getText() << "\""; -} - -void ASTDumper::visitInlineCommandComment(const InlineCommandComment *C) { - OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; - switch (C->getRenderKind()) { - case InlineCommandComment::RenderNormal: - OS << " RenderNormal"; - break; - case InlineCommandComment::RenderBold: - OS << " RenderBold"; - break; - case InlineCommandComment::RenderMonospaced: - OS << " RenderMonospaced"; - break; - case InlineCommandComment::RenderEmphasized: - OS << " RenderEmphasized"; - break; - } - - for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) - OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; -} - -void ASTDumper::visitHTMLStartTagComment(const HTMLStartTagComment *C) { - OS << " Name=\"" << C->getTagName() << "\""; - if (C->getNumAttrs() != 0) { - OS << " Attrs: "; - for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) { - const HTMLStartTagComment::Attribute &Attr = C->getAttr(i); - OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\""; - } - } - if (C->isSelfClosing()) - OS << " SelfClosing"; -} - -void ASTDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) { - OS << " Name=\"" << C->getTagName() << "\""; -} - -void ASTDumper::visitBlockCommandComment(const BlockCommandComment *C) { - OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; - for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) - OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; -} - -void ASTDumper::visitParamCommandComment(const ParamCommandComment *C) { - OS << " " << ParamCommandComment::getDirectionAsString(C->getDirection()); - - if (C->isDirectionExplicit()) - OS << " explicitly"; - else - OS << " implicitly"; - - if (C->hasParamName()) { - if (C->isParamIndexValid()) - OS << " Param=\"" << C->getParamName(FC) << "\""; - else - OS << " Param=\"" << C->getParamNameAsWritten() << "\""; - } - - if (C->isParamIndexValid() && !C->isVarArgParam()) - OS << " ParamIndex=" << C->getParamIndex(); -} - -void ASTDumper::visitTParamCommandComment(const TParamCommandComment *C) { - if (C->hasParamName()) { - if (C->isPositionValid()) - OS << " Param=\"" << C->getParamName(FC) << "\""; - else - OS << " Param=\"" << C->getParamNameAsWritten() << "\""; - } - - if (C->isPositionValid()) { - OS << " Position=<"; - for (unsigned i = 0, e = C->getDepth(); i != e; ++i) { - OS << C->getIndex(i); - if (i != e - 1) - OS << ", "; - } - OS << ">"; - } -} - -void ASTDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) { - OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"" - " CloseName=\"" << C->getCloseName() << "\""; -} - -void ASTDumper::visitVerbatimBlockLineComment( - const VerbatimBlockLineComment *C) { - OS << " Text=\"" << C->getText() << "\""; -} - -void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) { - OS << " Text=\"" << C->getText() << "\""; -} - //===----------------------------------------------------------------------===// // Type method implementations //===----------------------------------------------------------------------===// @@ -2846,12 +2403,16 @@ LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const { void Comment::dump(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) const { const FullComment *FC = dyn_cast<FullComment>(this); + if (!FC) + return; ASTDumper D(OS, Traits, SM); - D.dumpFullComment(FC); + D.dumpComment(FC, FC); } LLVM_DUMP_METHOD void Comment::dumpColor() const { const FullComment *FC = dyn_cast<FullComment>(this); + if (!FC) + return; ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); - D.dumpFullComment(FC); + D.dumpComment(FC, FC); } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 884d60df76..6ba80cdaa7 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -71,32 +71,43 @@ namespace clang { - unsigned ASTImporter::getFieldIndex(Decl *F) { - assert(F && (isa<FieldDecl>(*F) || isa<IndirectFieldDecl>(*F)) && - "Try to get field index for non-field."); - - auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); - if (!Owner) - return 0; - - unsigned Index = 1; - for (const auto *D : Owner->decls()) { - if (D == F) - return Index; - - if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) - ++Index; + using llvm::make_error; + using llvm::Error; + using llvm::Expected; + using ExpectedType = llvm::Expected<QualType>; + using ExpectedStmt = llvm::Expected<Stmt *>; + using ExpectedExpr = llvm::Expected<Expr *>; + using ExpectedDecl = llvm::Expected<Decl *>; + using ExpectedSLoc = llvm::Expected<SourceLocation>; + + std::string ImportError::toString() const { + // FIXME: Improve error texts. + switch (Error) { + case NameConflict: + return "NameConflict"; + case UnsupportedConstruct: + return "UnsupportedConstruct"; + case Unknown: + return "Unknown error"; } + llvm_unreachable("Invalid error code."); + return "Invalid error code."; + } - llvm_unreachable("Field was not found in its parent context."); + void ImportError::log(raw_ostream &OS) const { + OS << toString(); + } - return 0; + std::error_code ImportError::convertToErrorCode() const { + llvm_unreachable("Function not implemented."); } + char ImportError::ID; + template <class T> - SmallVector<Decl*, 2> + SmallVector<Decl *, 2> getCanonicalForwardRedeclChain(Redeclarable<T>* D) { - SmallVector<Decl*, 2> Redecls; + SmallVector<Decl *, 2> Redecls; for (auto *R : D->getFirstDecl()->redecls()) { if (R != D->getFirstDecl()) Redecls.push_back(R); @@ -121,12 +132,132 @@ namespace clang { To->setIsUsed(); } - class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>, - public DeclVisitor<ASTNodeImporter, Decl *>, - public StmtVisitor<ASTNodeImporter, Stmt *> { + Optional<unsigned> ASTImporter::getFieldIndex(Decl *F) { + assert(F && (isa<FieldDecl>(*F) || isa<IndirectFieldDecl>(*F)) && + "Try to get field index for non-field."); + + auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); + if (!Owner) + return None; + + unsigned Index = 0; + for (const auto *D : Owner->decls()) { + if (D == F) + return Index; + + if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) + ++Index; + } + + llvm_unreachable("Field was not found in its parent context."); + + return None; + } + + // FIXME: Temporary until every import returns Expected. + template <> + LLVM_NODISCARD Error + ASTImporter::importInto(SourceLocation &To, const SourceLocation &From) { + To = Import(From); + if (From.isValid() && To.isInvalid()) + return llvm::make_error<ImportError>(); + return Error::success(); + } + // FIXME: Temporary until every import returns Expected. + template <> + LLVM_NODISCARD Error + ASTImporter::importInto(QualType &To, const QualType &From) { + To = Import(From); + if (!From.isNull() && To.isNull()) + return llvm::make_error<ImportError>(); + return Error::success(); + } + + class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, ExpectedType>, + public DeclVisitor<ASTNodeImporter, ExpectedDecl>, + public StmtVisitor<ASTNodeImporter, ExpectedStmt> { ASTImporter &Importer; - // Wrapper for an overload set. + // Use this instead of Importer.importInto . + template <typename ImportT> + LLVM_NODISCARD Error importInto(ImportT &To, const ImportT &From) { + return Importer.importInto(To, From); + } + + // Use this to import pointers of specific type. + template <typename ImportT> + LLVM_NODISCARD Error importInto(ImportT *&To, ImportT *From) { + auto ToI = Importer.Import(From); + if (!ToI && From) + return make_error<ImportError>(); + To = cast_or_null<ImportT>(ToI); + return Error::success(); + // FIXME: This should be the final code. + //auto ToOrErr = Importer.Import(From); + //if (ToOrErr) { + // To = cast_or_null<ImportT>(*ToOrErr); + //} + //return ToOrErr.takeError(); + } + + // Call the import function of ASTImporter for a baseclass of type `T` and + // cast the return value to `T`. + template <typename T> + Expected<T *> import(T *From) { + auto *To = Importer.Import(From); + if (!To && From) + return make_error<ImportError>(); + return cast_or_null<T>(To); + // FIXME: This should be the final code. + //auto ToOrErr = Importer.Import(From); + //if (!ToOrErr) + // return ToOrErr.takeError(); + //return cast_or_null<T>(*ToOrErr); + } + + template <typename T> + Expected<T *> import(const T *From) { + return import(const_cast<T *>(From)); + } + + // Call the import function of ASTImporter for type `T`. + template <typename T> + Expected<T> import(const T &From) { + T To = Importer.Import(From); + T DefaultT; + if (To == DefaultT && !(From == DefaultT)) + return make_error<ImportError>(); + return To; + // FIXME: This should be the final code. + //return Importer.Import(From); + } + + template <class T> + Expected<std::tuple<T>> + importSeq(const T &From) { + Expected<T> ToOrErr = import(From); + if (!ToOrErr) + return ToOrErr.takeError(); + return std::make_tuple<T>(std::move(*ToOrErr)); + } + + // Import multiple objects with a single function call. + // This should work for every type for which a variant of `import` exists. + // The arguments are processed from left to right and import is stopped on + // first error. + template <class THead, class... TTail> + Expected<std::tuple<THead, TTail...>> + importSeq(const THead &FromHead, const TTail &...FromTail) { + Expected<std::tuple<THead>> ToHeadOrErr = importSeq(FromHead); + if (!ToHeadOrErr) + return ToHeadOrErr.takeError(); + Expected<std::tuple<TTail...>> ToTailOrErr = importSeq(FromTail...); + if (!ToTailOrErr) + return ToTailOrErr.takeError(); + return std::tuple_cat(*ToHeadOrErr, *ToTailOrErr); + } + +// Wrapper for an overload set. template <typename ToDeclT> struct CallOverloadedCreateFun { template <typename... Args> auto operator()(Args &&... args) @@ -171,6 +302,11 @@ namespace clang { LLVM_NODISCARD bool GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun, FromDeclT *FromD, Args &&... args) { + // FIXME: This code is needed later. + //if (Importer.getImportDeclErrorIfAny(FromD)) { + // ToD = nullptr; + // return true; // Already imported but with error. + //} ToD = cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD)); if (ToD) return true; // Already imported. @@ -194,84 +330,82 @@ namespace clang { public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} - using TypeVisitor<ASTNodeImporter, QualType>::Visit; - using DeclVisitor<ASTNodeImporter, Decl *>::Visit; - using StmtVisitor<ASTNodeImporter, Stmt *>::Visit; + using TypeVisitor<ASTNodeImporter, ExpectedType>::Visit; + using DeclVisitor<ASTNodeImporter, ExpectedDecl>::Visit; + using StmtVisitor<ASTNodeImporter, ExpectedStmt>::Visit; // Importing types - QualType VisitType(const Type *T); - QualType VisitAtomicType(const AtomicType *T); - QualType VisitBuiltinType(const BuiltinType *T); - QualType VisitDecayedType(const DecayedType *T); - QualType VisitComplexType(const ComplexType *T); - QualType VisitPointerType(const PointerType *T); - QualType VisitBlockPointerType(const BlockPointerType *T); - QualType VisitLValueReferenceType(const LValueReferenceType *T); - QualType VisitRValueReferenceType(const RValueReferenceType *T); - QualType VisitMemberPointerType(const MemberPointerType *T); - QualType VisitConstantArrayType(const ConstantArrayType *T); - QualType VisitIncompleteArrayType(const IncompleteArrayType *T); - QualType VisitVariableArrayType(const VariableArrayType *T); - QualType VisitDependentSizedArrayType(const DependentSizedArrayType *T); + ExpectedType VisitType(const Type *T); + ExpectedType VisitAtomicType(const AtomicType *T); + ExpectedType VisitBuiltinType(const BuiltinType *T); + ExpectedType VisitDecayedType(const DecayedType *T); + ExpectedType VisitComplexType(const ComplexType *T); + ExpectedType VisitPointerType(const PointerType *T); + ExpectedType VisitBlockPointerType(const BlockPointerType *T); + ExpectedType VisitLValueReferenceType(const LValueReferenceType *T); + ExpectedType VisitRValueReferenceType(const RValueReferenceType *T); + ExpectedType VisitMemberPointerType(const MemberPointerType *T); + ExpectedType VisitConstantArrayType(const ConstantArrayType *T); + ExpectedType VisitIncompleteArrayType(const IncompleteArrayType *T); + ExpectedType VisitVariableArrayType(const VariableArrayType *T); + ExpectedType VisitDependentSizedArrayType(const DependentSizedArrayType *T); // FIXME: DependentSizedExtVectorType - QualType VisitVectorType(const VectorType *T); - QualType VisitExtVectorType(const ExtVectorType *T); - QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T); - QualType VisitFunctionProtoType(const FunctionProtoType *T); - QualType VisitUnresolvedUsingType(const UnresolvedUsingType *T); - QualType VisitParenType(const ParenType *T); - QualType VisitTypedefType(const TypedefType *T); - QualType VisitTypeOfExprType(const TypeOfExprType *T); + ExpectedType VisitVectorType(const VectorType *T); + ExpectedType VisitExtVectorType(const ExtVectorType *T); + ExpectedType VisitFunctionNoProtoType(const FunctionNoProtoType *T); + ExpectedType VisitFunctionProtoType(const FunctionProtoType *T); + ExpectedType VisitUnresolvedUsingType(const UnresolvedUsingType *T); + ExpectedType VisitParenType(const ParenType *T); + ExpectedType VisitTypedefType(const TypedefType *T); + ExpectedType VisitTypeOfExprType(const TypeOfExprType *T); // FIXME: DependentTypeOfExprType - QualType VisitTypeOfType(const TypeOfType *T); - QualType VisitDecltypeType(const DecltypeType *T); - QualType VisitUnaryTransformType(const UnaryTransformType *T); - QualType VisitAutoType(const AutoType *T); - QualType VisitInjectedClassNameType(const InjectedClassNameType *T); + ExpectedType VisitTypeOfType(const TypeOfType *T); + ExpectedType VisitDecltypeType(const DecltypeType *T); + ExpectedType VisitUnaryTransformType(const UnaryTransformType *T); + ExpectedType VisitAutoType(const AutoType *T); + ExpectedType VisitInjectedClassNameType(const InjectedClassNameType *T); // FIXME: DependentDecltypeType - QualType VisitRecordType(const RecordType *T); - QualType VisitEnumType(const EnumType *T); - QualType VisitAttributedType(const AttributedType *T); - QualType VisitTemplateTypeParmType(const TemplateTypeParmType *T); - QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T); - QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); - QualType VisitElaboratedType(const ElaboratedType *T); - QualType VisitDependentNameType(const DependentNameType *T); - QualType VisitPackExpansionType(const PackExpansionType *T); - QualType VisitDependentTemplateSpecializationType( + ExpectedType VisitRecordType(const RecordType *T); + ExpectedType VisitEnumType(const EnumType *T); + ExpectedType VisitAttributedType(const AttributedType *T); + ExpectedType VisitTemplateTypeParmType(const TemplateTypeParmType *T); + ExpectedType VisitSubstTemplateTypeParmType( + const SubstTemplateTypeParmType *T); + ExpectedType VisitTemplateSpecializationType( + const TemplateSpecializationType *T); + ExpectedType VisitElaboratedType(const ElaboratedType *T); + ExpectedType VisitDependentNameType(const DependentNameType *T); + ExpectedType VisitPackExpansionType(const PackExpansionType *T); + ExpectedType VisitDependentTemplateSpecializationType( const DependentTemplateSpecializationType *T); - QualType VisitObjCInterfaceType(const ObjCInterfaceType *T); - QualType VisitObjCObjectType(const ObjCObjectType *T); - QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); + ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T); + ExpectedType VisitObjCObjectType(const ObjCObjectType *T); + ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); // Importing declarations - bool ImportDeclParts(NamedDecl *D, DeclContext *&DC, - DeclContext *&LexicalDC, DeclarationName &Name, - NamedDecl *&ToD, SourceLocation &Loc); - void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr); - void ImportDeclarationNameLoc(const DeclarationNameInfo &From, - DeclarationNameInfo& To); - void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); - void ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); - - bool ImportCastPath(CastExpr *E, CXXCastPath &Path); + Error ImportDeclParts( + NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, + DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc); + Error ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr); + Error ImportDeclarationNameLoc( + const DeclarationNameInfo &From, DeclarationNameInfo &To); + Error ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + Error ImportDeclContext( + Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC); + Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); + + Expected<CXXCastPath> ImportCastPath(CastExpr *E); using Designator = DesignatedInitExpr::Designator; - Designator ImportDesignator(const Designator &D); - - Optional<LambdaCapture> ImportLambdaCapture(const LambdaCapture &From); - /// What we should import from the definition. enum ImportDefinitionKind { /// Import the default subset of the definition, which might be /// nothing (if minimal import is set) or might be everything (if minimal /// import is not set). IDK_Default, - /// Import everything. IDK_Everything, - /// Import only the bare bones needed to establish a valid /// DeclContext. IDK_Basic @@ -282,41 +416,44 @@ namespace clang { (IDK == IDK_Default && !Importer.isMinimalImport()); } - bool ImportInitializer(VarDecl *From, VarDecl *To); - bool ImportDefinition(RecordDecl *From, RecordDecl *To, - ImportDefinitionKind Kind = IDK_Default); - bool ImportDefinition(EnumDecl *From, EnumDecl *To, - ImportDefinitionKind Kind = IDK_Default); - bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, - ImportDefinitionKind Kind = IDK_Default); - bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To, - ImportDefinitionKind Kind = IDK_Default); - TemplateParameterList *ImportTemplateParameterList( + Error ImportInitializer(VarDecl *From, VarDecl *To); + Error ImportDefinition( + RecordDecl *From, RecordDecl *To, + ImportDefinitionKind Kind = IDK_Default); + Error ImportDefinition( + EnumDecl *From, EnumDecl *To, + ImportDefinitionKind Kind = IDK_Default); + Error ImportDefinition( + ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, + ImportDefinitionKind Kind = IDK_Default); + Error ImportDefinition( + ObjCProtocolDecl *From, ObjCProtocolDecl *To, + ImportDefinitionKind Kind = IDK_Default); + Expected<TemplateParameterList *> ImportTemplateParameterList( TemplateParameterList *Params); - TemplateArgument ImportTemplateArgument(const TemplateArgument &From); - Optional<TemplateArgumentLoc> ImportTemplateArgumentLoc( - const TemplateArgumentLoc &TALoc); - bool ImportTemplateArguments(const TemplateArgument *FromArgs, - unsigned NumFromArgs, - SmallVectorImpl<TemplateArgument> &ToArgs); + Error ImportTemplateArguments( + const TemplateArgument *FromArgs, unsigned NumFromArgs, + SmallVectorImpl<TemplateArgument> &ToArgs); + Expected<TemplateArgument> + ImportTemplateArgument(const TemplateArgument &From); template <typename InContainerTy> - bool ImportTemplateArgumentListInfo(const InContainerTy &Container, - TemplateArgumentListInfo &ToTAInfo); + Error ImportTemplateArgumentListInfo( + const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo); template<typename InContainerTy> - bool ImportTemplateArgumentListInfo(SourceLocation FromLAngleLoc, - SourceLocation FromRAngleLoc, - const InContainerTy &Container, - TemplateArgumentListInfo &Result); + Error ImportTemplateArgumentListInfo( + SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, + const InContainerTy &Container, TemplateArgumentListInfo &Result); using TemplateArgsTy = SmallVector<TemplateArgument, 8>; - using OptionalTemplateArgsTy = Optional<TemplateArgsTy>; - std::tuple<FunctionTemplateDecl *, OptionalTemplateArgsTy> + using FunctionTemplateAndArgsTy = + std::tuple<FunctionTemplateDecl *, TemplateArgsTy>; + Expected<FunctionTemplateAndArgsTy> ImportFunctionTemplateWithTemplateArgsFromSpecialization( FunctionDecl *FromFD); - bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); + Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); bool IsStructuralMatch(Decl *From, Decl *To, bool Complain); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, @@ -330,258 +467,498 @@ namespace clang { bool IsStructuralMatch(FunctionDecl *From, FunctionDecl *To); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); - Decl *VisitDecl(Decl *D); - Decl *VisitEmptyDecl(EmptyDecl *D); - Decl *VisitAccessSpecDecl(AccessSpecDecl *D); - Decl *VisitStaticAssertDecl(StaticAssertDecl *D); - Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); - Decl *VisitNamespaceDecl(NamespaceDecl *D); - Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); - Decl *VisitTypedefDecl(TypedefDecl *D); - Decl *VisitTypeAliasDecl(TypeAliasDecl *D); - Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); - Decl *VisitLabelDecl(LabelDecl *D); - Decl *VisitEnumDecl(EnumDecl *D); - Decl *VisitRecordDecl(RecordDecl *D); - Decl *VisitEnumConstantDecl(EnumConstantDecl *D); - Decl *VisitFunctionDecl(FunctionDecl *D); - Decl *VisitCXXMethodDecl(CXXMethodDecl *D); - Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D); - Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D); - Decl *VisitCXXConversionDecl(CXXConversionDecl *D); - Decl *VisitFieldDecl(FieldDecl *D); - Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D); - Decl *VisitFriendDecl(FriendDecl *D); - Decl *VisitObjCIvarDecl(ObjCIvarDecl *D); - Decl *VisitVarDecl(VarDecl *D); - Decl *VisitImplicitParamDecl(ImplicitParamDecl *D); - Decl *VisitParmVarDecl(ParmVarDecl *D); - Decl *VisitObjCMethodDecl(ObjCMethodDecl *D); - Decl *VisitObjCTypeParamDecl(ObjCTypeParamDecl *D); - Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D); - Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D); - Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D); - Decl *VisitUsingDecl(UsingDecl *D); - Decl *VisitUsingShadowDecl(UsingShadowDecl *D); - Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D); - Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); - Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - - ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list); - Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); - Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); - Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D); - Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D); - Decl *VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); - Decl *VisitClassTemplateDecl(ClassTemplateDecl *D); - Decl *VisitClassTemplateSpecializationDecl( + ExpectedDecl VisitDecl(Decl *D); + ExpectedDecl VisitImportDecl(ImportDecl *D); + ExpectedDecl VisitEmptyDecl(EmptyDecl *D); + ExpectedDecl VisitAccessSpecDecl(AccessSpecDecl *D); + ExpectedDecl VisitStaticAssertDecl(StaticAssertDecl *D); + ExpectedDecl VisitTranslationUnitDecl(TranslationUnitDecl *D); + ExpectedDecl VisitNamespaceDecl(NamespaceDecl *D); + ExpectedDecl VisitNamespaceAliasDecl(NamespaceAliasDecl *D); + ExpectedDecl VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); + ExpectedDecl VisitTypedefDecl(TypedefDecl *D); + ExpectedDecl VisitTypeAliasDecl(TypeAliasDecl *D); + ExpectedDecl VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); + ExpectedDecl VisitLabelDecl(LabelDecl *D); + ExpectedDecl VisitEnumDecl(EnumDecl *D); + ExpectedDecl VisitRecordDecl(RecordDecl *D); + ExpectedDecl VisitEnumConstantDecl(EnumConstantDecl *D); + ExpectedDecl VisitFunctionDecl(FunctionDecl *D); + ExpectedDecl VisitCXXMethodDecl(CXXMethodDecl *D); + ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D); + ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D); + ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D); + ExpectedDecl VisitFieldDecl(FieldDecl *D); + ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D); + ExpectedDecl VisitFriendDecl(FriendDecl *D); + ExpectedDecl VisitObjCIvarDecl(ObjCIvarDecl *D); + ExpectedDecl VisitVarDecl(VarDecl *D); + ExpectedDecl VisitImplicitParamDecl(ImplicitParamDecl *D); + ExpectedDecl VisitParmVarDecl(ParmVarDecl *D); + ExpectedDecl VisitObjCMethodDecl(ObjCMethodDecl *D); + ExpectedDecl VisitObjCTypeParamDecl(ObjCTypeParamDecl *D); + ExpectedDecl VisitObjCCategoryDecl(ObjCCategoryDecl *D); + ExpectedDecl VisitObjCProtocolDecl(ObjCProtocolDecl *D); + ExpectedDecl VisitLinkageSpecDecl(LinkageSpecDecl *D); + ExpectedDecl VisitUsingDecl(UsingDecl *D); + ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D); + ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); + ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + + Expected<ObjCTypeParamList *> + ImportObjCTypeParamList(ObjCTypeParamList *list); + + ExpectedDecl VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); + ExpectedDecl VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); + ExpectedDecl VisitObjCImplementationDecl(ObjCImplementationDecl *D); + ExpectedDecl VisitObjCPropertyDecl(ObjCPropertyDecl *D); + ExpectedDecl VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); + ExpectedDecl VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); + ExpectedDecl VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); + ExpectedDecl VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); + ExpectedDecl VisitClassTemplateDecl(ClassTemplateDecl *D); + ExpectedDecl VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D); - Decl *VisitVarTemplateDecl(VarTemplateDecl *D); - Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); - Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); + ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D); + ExpectedDecl VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); + ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D); // Importing statements - DeclGroupRef ImportDeclGroup(DeclGroupRef DG); - - Stmt *VisitStmt(Stmt *S); - Stmt *VisitGCCAsmStmt(GCCAsmStmt *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); + ExpectedStmt VisitStmt(Stmt *S); + ExpectedStmt VisitGCCAsmStmt(GCCAsmStmt *S); + ExpectedStmt VisitDeclStmt(DeclStmt *S); + ExpectedStmt VisitNullStmt(NullStmt *S); + ExpectedStmt VisitCompoundStmt(CompoundStmt *S); + ExpectedStmt VisitCaseStmt(CaseStmt *S); + ExpectedStmt VisitDefaultStmt(DefaultStmt *S); + ExpectedStmt VisitLabelStmt(LabelStmt *S); + ExpectedStmt VisitAttributedStmt(AttributedStmt *S); + ExpectedStmt VisitIfStmt(IfStmt *S); + ExpectedStmt VisitSwitchStmt(SwitchStmt *S); + ExpectedStmt VisitWhileStmt(WhileStmt *S); + ExpectedStmt VisitDoStmt(DoStmt *S); + ExpectedStmt VisitForStmt(ForStmt *S); + ExpectedStmt VisitGotoStmt(GotoStmt *S); + ExpectedStmt VisitIndirectGotoStmt(IndirectGotoStmt *S); + ExpectedStmt VisitContinueStmt(ContinueStmt *S); + ExpectedStmt VisitBreakStmt(BreakStmt *S); + ExpectedStmt VisitReturnStmt(ReturnStmt *S); // FIXME: MSAsmStmt // FIXME: SEHExceptStmt // FIXME: SEHFinallyStmt // FIXME: SEHTryStmt // FIXME: SEHLeaveStmt // FIXME: CapturedStmt - Stmt *VisitCXXCatchStmt(CXXCatchStmt *S); - Stmt *VisitCXXTryStmt(CXXTryStmt *S); - Stmt *VisitCXXForRangeStmt(CXXForRangeStmt *S); + ExpectedStmt VisitCXXCatchStmt(CXXCatchStmt *S); + ExpectedStmt VisitCXXTryStmt(CXXTryStmt *S); + ExpectedStmt 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); + ExpectedStmt VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); + ExpectedStmt VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); + ExpectedStmt VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S); + ExpectedStmt VisitObjCAtTryStmt(ObjCAtTryStmt *S); + ExpectedStmt VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); + ExpectedStmt VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); + ExpectedStmt VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); // Importing expressions - Expr *VisitExpr(Expr *E); - Expr *VisitVAArgExpr(VAArgExpr *E); - Expr *VisitGNUNullExpr(GNUNullExpr *E); - Expr *VisitPredefinedExpr(PredefinedExpr *E); - Expr *VisitDeclRefExpr(DeclRefExpr *E); - Expr *VisitImplicitValueInitExpr(ImplicitValueInitExpr *ILE); - Expr *VisitDesignatedInitExpr(DesignatedInitExpr *E); - Expr *VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); - Expr *VisitIntegerLiteral(IntegerLiteral *E); - Expr *VisitFloatingLiteral(FloatingLiteral *E); - Expr *VisitImaginaryLiteral(ImaginaryLiteral *E); - Expr *VisitCharacterLiteral(CharacterLiteral *E); - Expr *VisitStringLiteral(StringLiteral *E); - Expr *VisitCompoundLiteralExpr(CompoundLiteralExpr *E); - Expr *VisitAtomicExpr(AtomicExpr *E); - Expr *VisitAddrLabelExpr(AddrLabelExpr *E); - Expr *VisitParenExpr(ParenExpr *E); - Expr *VisitParenListExpr(ParenListExpr *E); - Expr *VisitStmtExpr(StmtExpr *E); - Expr *VisitUnaryOperator(UnaryOperator *E); - Expr *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); - Expr *VisitBinaryOperator(BinaryOperator *E); - Expr *VisitConditionalOperator(ConditionalOperator *E); - Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E); - Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E); - Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); - Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E); - Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E); - Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E); - Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); - Expr *VisitExplicitCastExpr(ExplicitCastExpr *E); - Expr *VisitOffsetOfExpr(OffsetOfExpr *OE); - Expr *VisitCXXThrowExpr(CXXThrowExpr *E); - Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E); - Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); - Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); - Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); - Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE); - Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); - Expr *VisitPackExpansionExpr(PackExpansionExpr *E); - Expr *VisitSizeOfPackExpr(SizeOfPackExpr *E); - Expr *VisitCXXNewExpr(CXXNewExpr *CE); - Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E); - Expr *VisitCXXConstructExpr(CXXConstructExpr *E); - Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); - Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); - Expr *VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E); - Expr *VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *CE); - Expr *VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E); - Expr *VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E); - Expr *VisitExprWithCleanups(ExprWithCleanups *EWC); - Expr *VisitCXXThisExpr(CXXThisExpr *E); - Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); - Expr *VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); - Expr *VisitMemberExpr(MemberExpr *E); - Expr *VisitCallExpr(CallExpr *E); - Expr *VisitLambdaExpr(LambdaExpr *LE); - Expr *VisitInitListExpr(InitListExpr *E); - Expr *VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E); - Expr *VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E); - Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); - Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); - Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); - Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E); - Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E); - Expr *VisitTypeTraitExpr(TypeTraitExpr *E); - Expr *VisitCXXTypeidExpr(CXXTypeidExpr *E); + ExpectedStmt VisitExpr(Expr *E); + ExpectedStmt VisitVAArgExpr(VAArgExpr *E); + ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); + ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); + ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E); + ExpectedStmt VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); + ExpectedStmt VisitDesignatedInitExpr(DesignatedInitExpr *E); + ExpectedStmt VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); + ExpectedStmt VisitIntegerLiteral(IntegerLiteral *E); + ExpectedStmt VisitFloatingLiteral(FloatingLiteral *E); + ExpectedStmt VisitImaginaryLiteral(ImaginaryLiteral *E); + ExpectedStmt VisitCharacterLiteral(CharacterLiteral *E); + ExpectedStmt VisitStringLiteral(StringLiteral *E); + ExpectedStmt VisitCompoundLiteralExpr(CompoundLiteralExpr *E); + ExpectedStmt VisitAtomicExpr(AtomicExpr *E); + ExpectedStmt VisitAddrLabelExpr(AddrLabelExpr *E); + ExpectedStmt VisitConstantExpr(ConstantExpr *E); + ExpectedStmt VisitParenExpr(ParenExpr *E); + ExpectedStmt VisitParenListExpr(ParenListExpr *E); + ExpectedStmt VisitStmtExpr(StmtExpr *E); + ExpectedStmt VisitUnaryOperator(UnaryOperator *E); + ExpectedStmt VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); + ExpectedStmt VisitBinaryOperator(BinaryOperator *E); + ExpectedStmt VisitConditionalOperator(ConditionalOperator *E); + ExpectedStmt VisitBinaryConditionalOperator(BinaryConditionalOperator *E); + ExpectedStmt VisitOpaqueValueExpr(OpaqueValueExpr *E); + ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); + ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E); + ExpectedStmt VisitArraySubscriptExpr(ArraySubscriptExpr *E); + ExpectedStmt VisitCompoundAssignOperator(CompoundAssignOperator *E); + ExpectedStmt VisitImplicitCastExpr(ImplicitCastExpr *E); + ExpectedStmt VisitExplicitCastExpr(ExplicitCastExpr *E); + ExpectedStmt VisitOffsetOfExpr(OffsetOfExpr *OE); + ExpectedStmt VisitCXXThrowExpr(CXXThrowExpr *E); + ExpectedStmt VisitCXXNoexceptExpr(CXXNoexceptExpr *E); + ExpectedStmt VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); + ExpectedStmt VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); + ExpectedStmt VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); + ExpectedStmt VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); + ExpectedStmt VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); + ExpectedStmt VisitPackExpansionExpr(PackExpansionExpr *E); + ExpectedStmt VisitSizeOfPackExpr(SizeOfPackExpr *E); + ExpectedStmt VisitCXXNewExpr(CXXNewExpr *E); + ExpectedStmt VisitCXXDeleteExpr(CXXDeleteExpr *E); + ExpectedStmt VisitCXXConstructExpr(CXXConstructExpr *E); + ExpectedStmt VisitCXXMemberCallExpr(CXXMemberCallExpr *E); + ExpectedStmt VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); + ExpectedStmt VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E); + ExpectedStmt VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E); + ExpectedStmt VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E); + ExpectedStmt VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E); + ExpectedStmt VisitExprWithCleanups(ExprWithCleanups *E); + ExpectedStmt VisitCXXThisExpr(CXXThisExpr *E); + ExpectedStmt VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); + ExpectedStmt VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); + ExpectedStmt VisitMemberExpr(MemberExpr *E); + ExpectedStmt VisitCallExpr(CallExpr *E); + ExpectedStmt VisitLambdaExpr(LambdaExpr *LE); + ExpectedStmt VisitInitListExpr(InitListExpr *E); + ExpectedStmt VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E); + ExpectedStmt VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E); + ExpectedStmt VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); + ExpectedStmt VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); + ExpectedStmt VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); + ExpectedStmt VisitCXXNamedCastExpr(CXXNamedCastExpr *E); + ExpectedStmt VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E); + ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E); + ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E); template<typename IIter, typename OIter> - void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) { + Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { using ItemT = typename std::remove_reference<decltype(*Obegin)>::type; - - ASTImporter &ImporterRef = Importer; - std::transform(Ibegin, Iend, Obegin, - [&ImporterRef](ItemT From) -> ItemT { - return ImporterRef.Import(From); - }); - } - - template<typename IIter, typename OIter> - bool ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { - using ItemT = typename std::remove_reference<decltype(**Obegin)>::type; - - ASTImporter &ImporterRef = Importer; - bool Failed = false; - std::transform(Ibegin, Iend, Obegin, - [&ImporterRef, &Failed](ItemT *From) -> ItemT * { - auto *To = cast_or_null<ItemT>(ImporterRef.Import(From)); - if (!To && From) - Failed = true; - return To; - }); - return Failed; + for (; Ibegin != Iend; ++Ibegin, ++Obegin) { + Expected<ItemT> ToOrErr = import(*Ibegin); + if (!ToOrErr) + return ToOrErr.takeError(); + *Obegin = *ToOrErr; + } + return Error::success(); } + // Import every item from a container structure into an output container. + // If error occurs, stops at first error and returns the error. + // The output container should have space for all needed elements (it is not + // expanded, new items are put into from the beginning). template<typename InContainerTy, typename OutContainerTy> - bool ImportContainerChecked(const InContainerTy &InContainer, - OutContainerTy &OutContainer) { - return ImportArrayChecked(InContainer.begin(), InContainer.end(), - OutContainer.begin()); + Error ImportContainerChecked( + const InContainerTy &InContainer, OutContainerTy &OutContainer) { + return ImportArrayChecked( + InContainer.begin(), InContainer.end(), OutContainer.begin()); } template<typename InContainerTy, typename OIter> - bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { + Error ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); } - // Importing overrides. void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); - FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD); + Expected<FunctionDecl *> FindFunctionTemplateSpecialization( + FunctionDecl *FromFD); }; +// FIXME: Temporary until every import returns Expected. +template <> +Expected<TemplateName> ASTNodeImporter::import(const TemplateName &From) { + TemplateName To = Importer.Import(From); + if (To.isNull() && !From.isNull()) + return make_error<ImportError>(); + return To; +} + template <typename InContainerTy> -bool ASTNodeImporter::ImportTemplateArgumentListInfo( +Error ASTNodeImporter::ImportTemplateArgumentListInfo( SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, const InContainerTy &Container, TemplateArgumentListInfo &Result) { - TemplateArgumentListInfo ToTAInfo(Importer.Import(FromLAngleLoc), - Importer.Import(FromRAngleLoc)); - if (ImportTemplateArgumentListInfo(Container, ToTAInfo)) - return true; + auto ToLAngleLocOrErr = import(FromLAngleLoc); + if (!ToLAngleLocOrErr) + return ToLAngleLocOrErr.takeError(); + auto ToRAngleLocOrErr = import(FromRAngleLoc); + if (!ToRAngleLocOrErr) + return ToRAngleLocOrErr.takeError(); + + TemplateArgumentListInfo ToTAInfo(*ToLAngleLocOrErr, *ToRAngleLocOrErr); + if (auto Err = ImportTemplateArgumentListInfo(Container, ToTAInfo)) + return Err; Result = ToTAInfo; - return false; + return Error::success(); } template <> -bool ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>( +Error ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>( const TemplateArgumentListInfo &From, TemplateArgumentListInfo &Result) { return ImportTemplateArgumentListInfo( From.getLAngleLoc(), From.getRAngleLoc(), From.arguments(), Result); } template <> -bool ASTNodeImporter::ImportTemplateArgumentListInfo< - ASTTemplateArgumentListInfo>(const ASTTemplateArgumentListInfo &From, - TemplateArgumentListInfo &Result) { - return ImportTemplateArgumentListInfo(From.LAngleLoc, From.RAngleLoc, - From.arguments(), Result); +Error ASTNodeImporter::ImportTemplateArgumentListInfo< + ASTTemplateArgumentListInfo>( + const ASTTemplateArgumentListInfo &From, + TemplateArgumentListInfo &Result) { + return ImportTemplateArgumentListInfo( + From.LAngleLoc, From.RAngleLoc, From.arguments(), Result); } -std::tuple<FunctionTemplateDecl *, ASTNodeImporter::OptionalTemplateArgsTy> +Expected<ASTNodeImporter::FunctionTemplateAndArgsTy> ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( FunctionDecl *FromFD) { assert(FromFD->getTemplatedKind() == - FunctionDecl::TK_FunctionTemplateSpecialization); + FunctionDecl::TK_FunctionTemplateSpecialization); + + FunctionTemplateAndArgsTy Result; + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); - auto *Template = cast_or_null<FunctionTemplateDecl>( - Importer.Import(FTSInfo->getTemplate())); + if (Error Err = importInto(std::get<0>(Result), FTSInfo->getTemplate())) + return std::move(Err); // Import template arguments. auto TemplArgs = FTSInfo->TemplateArguments->asArray(); - TemplateArgsTy ToTemplArgs; - if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), - ToTemplArgs)) // Error during import. - return std::make_tuple(Template, OptionalTemplateArgsTy()); + if (Error Err = ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), + std::get<1>(Result))) + return std::move(Err); + + return Result; +} + +template <> +Expected<TemplateParameterList *> +ASTNodeImporter::import(TemplateParameterList *From) { + SmallVector<NamedDecl *, 4> To(From->size()); + if (Error Err = ImportContainerChecked(*From, To)) + return std::move(Err); + + ExpectedExpr ToRequiresClause = import(From->getRequiresClause()); + if (!ToRequiresClause) + return ToRequiresClause.takeError(); + + auto ToTemplateLocOrErr = import(From->getTemplateLoc()); + if (!ToTemplateLocOrErr) + return ToTemplateLocOrErr.takeError(); + auto ToLAngleLocOrErr = import(From->getLAngleLoc()); + if (!ToLAngleLocOrErr) + return ToLAngleLocOrErr.takeError(); + auto ToRAngleLocOrErr = import(From->getRAngleLoc()); + if (!ToRAngleLocOrErr) + return ToRAngleLocOrErr.takeError(); + + return TemplateParameterList::Create( + Importer.getToContext(), + *ToTemplateLocOrErr, + *ToLAngleLocOrErr, + To, + *ToRAngleLocOrErr, + *ToRequiresClause); +} + +template <> +Expected<TemplateArgument> +ASTNodeImporter::import(const TemplateArgument &From) { + switch (From.getKind()) { + case TemplateArgument::Null: + return TemplateArgument(); - return std::make_tuple(Template, ToTemplArgs); + case TemplateArgument::Type: { + ExpectedType ToTypeOrErr = import(From.getAsType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + return TemplateArgument(*ToTypeOrErr); + } + + case TemplateArgument::Integral: { + ExpectedType ToTypeOrErr = import(From.getIntegralType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + return TemplateArgument(From, *ToTypeOrErr); + } + + case TemplateArgument::Declaration: { + Expected<ValueDecl *> ToOrErr = import(From.getAsDecl()); + if (!ToOrErr) + return ToOrErr.takeError(); + ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + return TemplateArgument(*ToOrErr, *ToTypeOrErr); + } + + case TemplateArgument::NullPtr: { + ExpectedType ToTypeOrErr = import(From.getNullPtrType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true); + } + + case TemplateArgument::Template: { + Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate()); + if (!ToTemplateOrErr) + return ToTemplateOrErr.takeError(); + + return TemplateArgument(*ToTemplateOrErr); + } + + case TemplateArgument::TemplateExpansion: { + Expected<TemplateName> ToTemplateOrErr = + import(From.getAsTemplateOrTemplatePattern()); + if (!ToTemplateOrErr) + return ToTemplateOrErr.takeError(); + + return TemplateArgument( + *ToTemplateOrErr, From.getNumTemplateExpansions()); + } + + case TemplateArgument::Expression: + if (ExpectedExpr ToExpr = import(From.getAsExpr())) + return TemplateArgument(*ToExpr); + else + return ToExpr.takeError(); + + case TemplateArgument::Pack: { + SmallVector<TemplateArgument, 2> ToPack; + ToPack.reserve(From.pack_size()); + if (Error Err = ImportTemplateArguments( + From.pack_begin(), From.pack_size(), ToPack)) + return std::move(Err); + + return TemplateArgument( + llvm::makeArrayRef(ToPack).copy(Importer.getToContext())); + } + } + + llvm_unreachable("Invalid template argument kind"); +} + +template <> +Expected<TemplateArgumentLoc> +ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) { + Expected<TemplateArgument> ArgOrErr = import(TALoc.getArgument()); + if (!ArgOrErr) + return ArgOrErr.takeError(); + TemplateArgument Arg = *ArgOrErr; + + TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); + + TemplateArgumentLocInfo ToInfo; + if (Arg.getKind() == TemplateArgument::Expression) { + ExpectedExpr E = import(FromInfo.getAsExpr()); + if (!E) + return E.takeError(); + ToInfo = TemplateArgumentLocInfo(*E); + } else if (Arg.getKind() == TemplateArgument::Type) { + if (auto TSIOrErr = import(FromInfo.getAsTypeSourceInfo())) + ToInfo = TemplateArgumentLocInfo(*TSIOrErr); + else + return TSIOrErr.takeError(); + } else { + auto ToTemplateQualifierLocOrErr = + import(FromInfo.getTemplateQualifierLoc()); + if (!ToTemplateQualifierLocOrErr) + return ToTemplateQualifierLocOrErr.takeError(); + auto ToTemplateNameLocOrErr = import(FromInfo.getTemplateNameLoc()); + if (!ToTemplateNameLocOrErr) + return ToTemplateNameLocOrErr.takeError(); + auto ToTemplateEllipsisLocOrErr = + import(FromInfo.getTemplateEllipsisLoc()); + if (!ToTemplateEllipsisLocOrErr) + return ToTemplateEllipsisLocOrErr.takeError(); + + ToInfo = TemplateArgumentLocInfo( + *ToTemplateQualifierLocOrErr, + *ToTemplateNameLocOrErr, + *ToTemplateEllipsisLocOrErr); + } + + return TemplateArgumentLoc(Arg, ToInfo); +} + +template <> +Expected<DeclGroupRef> ASTNodeImporter::import(const DeclGroupRef &DG) { + if (DG.isNull()) + return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0); + size_t NumDecls = DG.end() - DG.begin(); + SmallVector<Decl *, 1> ToDecls; + ToDecls.reserve(NumDecls); + for (Decl *FromD : DG) { + if (auto ToDOrErr = import(FromD)) + ToDecls.push_back(*ToDOrErr); + else + return ToDOrErr.takeError(); + } + return DeclGroupRef::Create(Importer.getToContext(), + ToDecls.begin(), + NumDecls); +} + +template <> +Expected<ASTNodeImporter::Designator> +ASTNodeImporter::import(const Designator &D) { + if (D.isFieldDesignator()) { + IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName()); + + ExpectedSLoc ToDotLocOrErr = import(D.getDotLoc()); + if (!ToDotLocOrErr) + return ToDotLocOrErr.takeError(); + + ExpectedSLoc ToFieldLocOrErr = import(D.getFieldLoc()); + if (!ToFieldLocOrErr) + return ToFieldLocOrErr.takeError(); + + return Designator(ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr); + } + + ExpectedSLoc ToLBracketLocOrErr = import(D.getLBracketLoc()); + if (!ToLBracketLocOrErr) + return ToLBracketLocOrErr.takeError(); + + ExpectedSLoc ToRBracketLocOrErr = import(D.getRBracketLoc()); + if (!ToRBracketLocOrErr) + return ToRBracketLocOrErr.takeError(); + + if (D.isArrayDesignator()) + return Designator(D.getFirstExprIndex(), + *ToLBracketLocOrErr, *ToRBracketLocOrErr); + + ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc()); + if (!ToEllipsisLocOrErr) + return ToEllipsisLocOrErr.takeError(); + + assert(D.isArrayRangeDesignator()); + return Designator( + D.getFirstExprIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr, + *ToRBracketLocOrErr); +} + +template <> +Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) { + VarDecl *Var = nullptr; + if (From.capturesVariable()) { + if (auto VarOrErr = import(From.getCapturedVar())) + Var = *VarOrErr; + else + return VarOrErr.takeError(); + } + + auto LocationOrErr = import(From.getLocation()); + if (!LocationOrErr) + return LocationOrErr.takeError(); + + SourceLocation EllipsisLoc; + if (From.isPackExpansion()) + if (Error Err = importInto(EllipsisLoc, From.getEllipsisLoc())) + return std::move(Err); + + return LambdaCapture( + *LocationOrErr, From.isImplicit(), From.getCaptureKind(), Var, + EllipsisLoc); } } // namespace clang @@ -592,26 +969,30 @@ ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( using namespace clang; -QualType ASTNodeImporter::VisitType(const Type *T) { +ExpectedType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); - return {}; + return make_error<ImportError>(ImportError::UnsupportedConstruct); } -QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ - QualType UnderlyingType = Importer.Import(T->getValueType()); - if(UnderlyingType.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ + ExpectedType UnderlyingTypeOrErr = import(T->getValueType()); + if (!UnderlyingTypeOrErr) + return UnderlyingTypeOrErr.takeError(); - return Importer.getToContext().getAtomicType(UnderlyingType); + return Importer.getToContext().getAtomicType(*UnderlyingTypeOrErr); } -QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { +ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { switch (T->getKind()) { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: \ + return Importer.getToContext().Id##Ty; +#include "clang/Basic/OpenCLExtensionTypes.def" #define SHARED_SINGLETON_TYPE(Expansion) #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: return Importer.getToContext().SingletonId; @@ -651,183 +1032,196 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { llvm_unreachable("Invalid BuiltinType Kind!"); } -QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) { - QualType OrigT = Importer.Import(T->getOriginalType()); - if (OrigT.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitDecayedType(const DecayedType *T) { + ExpectedType ToOriginalTypeOrErr = import(T->getOriginalType()); + if (!ToOriginalTypeOrErr) + return ToOriginalTypeOrErr.takeError(); - return Importer.getToContext().getDecayedType(OrigT); + return Importer.getToContext().getDecayedType(*ToOriginalTypeOrErr); } -QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) { - QualType ToElementType = Importer.Import(T->getElementType()); - if (ToElementType.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitComplexType(const ComplexType *T) { + ExpectedType ToElementTypeOrErr = import(T->getElementType()); + if (!ToElementTypeOrErr) + return ToElementTypeOrErr.takeError(); - return Importer.getToContext().getComplexType(ToElementType); + return Importer.getToContext().getComplexType(*ToElementTypeOrErr); } -QualType ASTNodeImporter::VisitPointerType(const PointerType *T) { - QualType ToPointeeType = Importer.Import(T->getPointeeType()); - if (ToPointeeType.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitPointerType(const PointerType *T) { + ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); + if (!ToPointeeTypeOrErr) + return ToPointeeTypeOrErr.takeError(); - return Importer.getToContext().getPointerType(ToPointeeType); + return Importer.getToContext().getPointerType(*ToPointeeTypeOrErr); } -QualType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) { +ExpectedType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) { // FIXME: Check for blocks support in "to" context. - QualType ToPointeeType = Importer.Import(T->getPointeeType()); - if (ToPointeeType.isNull()) - return {}; + ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); + if (!ToPointeeTypeOrErr) + return ToPointeeTypeOrErr.takeError(); - return Importer.getToContext().getBlockPointerType(ToPointeeType); + return Importer.getToContext().getBlockPointerType(*ToPointeeTypeOrErr); } -QualType +ExpectedType ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) { // FIXME: Check for C++ support in "to" context. - QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten()); - if (ToPointeeType.isNull()) - return {}; + ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten()); + if (!ToPointeeTypeOrErr) + return ToPointeeTypeOrErr.takeError(); - return Importer.getToContext().getLValueReferenceType(ToPointeeType); + return Importer.getToContext().getLValueReferenceType(*ToPointeeTypeOrErr); } -QualType +ExpectedType ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) { // FIXME: Check for C++0x support in "to" context. - QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten()); - if (ToPointeeType.isNull()) - return {}; + ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten()); + if (!ToPointeeTypeOrErr) + return ToPointeeTypeOrErr.takeError(); - return Importer.getToContext().getRValueReferenceType(ToPointeeType); + return Importer.getToContext().getRValueReferenceType(*ToPointeeTypeOrErr); } -QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { +ExpectedType +ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { // FIXME: Check for C++ support in "to" context. - QualType ToPointeeType = Importer.Import(T->getPointeeType()); - if (ToPointeeType.isNull()) - return {}; + ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); + if (!ToPointeeTypeOrErr) + return ToPointeeTypeOrErr.takeError(); + + ExpectedType ClassTypeOrErr = import(QualType(T->getClass(), 0)); + if (!ClassTypeOrErr) + return ClassTypeOrErr.takeError(); - QualType ClassType = Importer.Import(QualType(T->getClass(), 0)); - return Importer.getToContext().getMemberPointerType(ToPointeeType, - ClassType.getTypePtr()); + return Importer.getToContext().getMemberPointerType( + *ToPointeeTypeOrErr, (*ClassTypeOrErr).getTypePtr()); } -QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { - QualType ToElementType = Importer.Import(T->getElementType()); - if (ToElementType.isNull()) - return {}; +ExpectedType +ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { + ExpectedType ToElementTypeOrErr = import(T->getElementType()); + if (!ToElementTypeOrErr) + return ToElementTypeOrErr.takeError(); - return Importer.getToContext().getConstantArrayType(ToElementType, + return Importer.getToContext().getConstantArrayType(*ToElementTypeOrErr, T->getSize(), T->getSizeModifier(), T->getIndexTypeCVRQualifiers()); } -QualType +ExpectedType ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) { - QualType ToElementType = Importer.Import(T->getElementType()); - if (ToElementType.isNull()) - return {}; + ExpectedType ToElementTypeOrErr = import(T->getElementType()); + if (!ToElementTypeOrErr) + return ToElementTypeOrErr.takeError(); - return Importer.getToContext().getIncompleteArrayType(ToElementType, + return Importer.getToContext().getIncompleteArrayType(*ToElementTypeOrErr, T->getSizeModifier(), T->getIndexTypeCVRQualifiers()); } -QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) { - QualType ToElementType = Importer.Import(T->getElementType()); - if (ToElementType.isNull()) - return {}; - - Expr *Size = Importer.Import(T->getSizeExpr()); - if (!Size) - return {}; +ExpectedType +ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) { + QualType ToElementType; + Expr *ToSizeExpr; + SourceRange ToBracketsRange; + if (auto Imp = importSeq( + T->getElementType(), T->getSizeExpr(), T->getBracketsRange())) + std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp; + else + return Imp.takeError(); - SourceRange Brackets = Importer.Import(T->getBracketsRange()); - return Importer.getToContext().getVariableArrayType(ToElementType, Size, - T->getSizeModifier(), - T->getIndexTypeCVRQualifiers(), - Brackets); + return Importer.getToContext().getVariableArrayType( + ToElementType, ToSizeExpr, T->getSizeModifier(), + T->getIndexTypeCVRQualifiers(), ToBracketsRange); } -QualType ASTNodeImporter::VisitDependentSizedArrayType( +ExpectedType ASTNodeImporter::VisitDependentSizedArrayType( const DependentSizedArrayType *T) { - QualType ToElementType = Importer.Import(T->getElementType()); - if (ToElementType.isNull()) - return {}; - + QualType ToElementType; + Expr *ToSizeExpr; + SourceRange ToBracketsRange; + if (auto Imp = importSeq( + T->getElementType(), T->getSizeExpr(), T->getBracketsRange())) + std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp; + else + return Imp.takeError(); // SizeExpr may be null if size is not specified directly. // For example, 'int a[]'. - Expr *Size = Importer.Import(T->getSizeExpr()); - if (!Size && T->getSizeExpr()) - return {}; - SourceRange Brackets = Importer.Import(T->getBracketsRange()); return Importer.getToContext().getDependentSizedArrayType( - ToElementType, Size, T->getSizeModifier(), T->getIndexTypeCVRQualifiers(), - Brackets); + ToElementType, ToSizeExpr, T->getSizeModifier(), + T->getIndexTypeCVRQualifiers(), ToBracketsRange); } -QualType ASTNodeImporter::VisitVectorType(const VectorType *T) { - QualType ToElementType = Importer.Import(T->getElementType()); - if (ToElementType.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitVectorType(const VectorType *T) { + ExpectedType ToElementTypeOrErr = import(T->getElementType()); + if (!ToElementTypeOrErr) + return ToElementTypeOrErr.takeError(); - return Importer.getToContext().getVectorType(ToElementType, + return Importer.getToContext().getVectorType(*ToElementTypeOrErr, T->getNumElements(), T->getVectorKind()); } -QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) { - QualType ToElementType = Importer.Import(T->getElementType()); - if (ToElementType.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) { + ExpectedType ToElementTypeOrErr = import(T->getElementType()); + if (!ToElementTypeOrErr) + return ToElementTypeOrErr.takeError(); - return Importer.getToContext().getExtVectorType(ToElementType, + return Importer.getToContext().getExtVectorType(*ToElementTypeOrErr, T->getNumElements()); } -QualType +ExpectedType ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { // FIXME: What happens if we're importing a function without a prototype // into C++? Should we make it variadic? - QualType ToResultType = Importer.Import(T->getReturnType()); - if (ToResultType.isNull()) - return {}; + ExpectedType ToReturnTypeOrErr = import(T->getReturnType()); + if (!ToReturnTypeOrErr) + return ToReturnTypeOrErr.takeError(); - return Importer.getToContext().getFunctionNoProtoType(ToResultType, + return Importer.getToContext().getFunctionNoProtoType(*ToReturnTypeOrErr, T->getExtInfo()); } -QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { - QualType ToResultType = Importer.Import(T->getReturnType()); - if (ToResultType.isNull()) - return {}; +ExpectedType +ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { + ExpectedType ToReturnTypeOrErr = import(T->getReturnType()); + if (!ToReturnTypeOrErr) + return ToReturnTypeOrErr.takeError(); // Import argument types SmallVector<QualType, 4> ArgTypes; for (const auto &A : T->param_types()) { - QualType ArgType = Importer.Import(A); - if (ArgType.isNull()) - return {}; - ArgTypes.push_back(ArgType); + ExpectedType TyOrErr = import(A); + if (!TyOrErr) + return TyOrErr.takeError(); + ArgTypes.push_back(*TyOrErr); } // Import exception types SmallVector<QualType, 4> ExceptionTypes; for (const auto &E : T->exceptions()) { - QualType ExceptionType = Importer.Import(E); - if (ExceptionType.isNull()) - return {}; - ExceptionTypes.push_back(ExceptionType); + ExpectedType TyOrErr = import(E); + if (!TyOrErr) + return TyOrErr.takeError(); + ExceptionTypes.push_back(*TyOrErr); } FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo(); FunctionProtoType::ExtProtoInfo ToEPI; + auto Imp = importSeq( + FromEPI.ExceptionSpec.NoexceptExpr, + FromEPI.ExceptionSpec.SourceDecl, + FromEPI.ExceptionSpec.SourceTemplate); + if (!Imp) + return Imp.takeError(); + ToEPI.ExtInfo = FromEPI.ExtInfo; ToEPI.Variadic = FromEPI.Variadic; ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn; @@ -835,112 +1229,108 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ToEPI.RefQualifier = FromEPI.RefQualifier; ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type; ToEPI.ExceptionSpec.Exceptions = ExceptionTypes; - ToEPI.ExceptionSpec.NoexceptExpr = - Importer.Import(FromEPI.ExceptionSpec.NoexceptExpr); - ToEPI.ExceptionSpec.SourceDecl = cast_or_null<FunctionDecl>( - Importer.Import(FromEPI.ExceptionSpec.SourceDecl)); - ToEPI.ExceptionSpec.SourceTemplate = cast_or_null<FunctionDecl>( - Importer.Import(FromEPI.ExceptionSpec.SourceTemplate)); + std::tie( + ToEPI.ExceptionSpec.NoexceptExpr, + ToEPI.ExceptionSpec.SourceDecl, + ToEPI.ExceptionSpec.SourceTemplate) = *Imp; - return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI); + return Importer.getToContext().getFunctionType( + *ToReturnTypeOrErr, ArgTypes, ToEPI); } -QualType ASTNodeImporter::VisitUnresolvedUsingType( +ExpectedType ASTNodeImporter::VisitUnresolvedUsingType( const UnresolvedUsingType *T) { - const auto *ToD = - cast_or_null<UnresolvedUsingTypenameDecl>(Importer.Import(T->getDecl())); - if (!ToD) - return {}; - - auto *ToPrevD = - cast_or_null<UnresolvedUsingTypenameDecl>( - Importer.Import(T->getDecl()->getPreviousDecl())); - if (!ToPrevD && T->getDecl()->getPreviousDecl()) - return {}; + UnresolvedUsingTypenameDecl *ToD; + Decl *ToPrevD; + if (auto Imp = importSeq(T->getDecl(), T->getDecl()->getPreviousDecl())) + std::tie(ToD, ToPrevD) = *Imp; + else + return Imp.takeError(); - return Importer.getToContext().getTypeDeclType(ToD, ToPrevD); + return Importer.getToContext().getTypeDeclType( + ToD, cast_or_null<TypeDecl>(ToPrevD)); } -QualType ASTNodeImporter::VisitParenType(const ParenType *T) { - QualType ToInnerType = Importer.Import(T->getInnerType()); - if (ToInnerType.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitParenType(const ParenType *T) { + ExpectedType ToInnerTypeOrErr = import(T->getInnerType()); + if (!ToInnerTypeOrErr) + return ToInnerTypeOrErr.takeError(); - return Importer.getToContext().getParenType(ToInnerType); + return Importer.getToContext().getParenType(*ToInnerTypeOrErr); } -QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { - auto *ToDecl = - dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl())); - if (!ToDecl) - return {}; +ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { + Expected<TypedefNameDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); - return Importer.getToContext().getTypeDeclType(ToDecl); + return Importer.getToContext().getTypeDeclType(*ToDeclOrErr); } -QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { - Expr *ToExpr = Importer.Import(T->getUnderlyingExpr()); - if (!ToExpr) - return {}; +ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { + ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); + if (!ToExprOrErr) + return ToExprOrErr.takeError(); - return Importer.getToContext().getTypeOfExprType(ToExpr); + return Importer.getToContext().getTypeOfExprType(*ToExprOrErr); } -QualType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { - QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType()); - if (ToUnderlyingType.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { + ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); + if (!ToUnderlyingTypeOrErr) + return ToUnderlyingTypeOrErr.takeError(); - return Importer.getToContext().getTypeOfType(ToUnderlyingType); + return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr); } -QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { +ExpectedType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { // FIXME: Make sure that the "to" context supports C++0x! - Expr *ToExpr = Importer.Import(T->getUnderlyingExpr()); - if (!ToExpr) - return {}; + ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); + if (!ToExprOrErr) + return ToExprOrErr.takeError(); - QualType UnderlyingType = Importer.Import(T->getUnderlyingType()); - if (UnderlyingType.isNull()) - return {}; + ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); + if (!ToUnderlyingTypeOrErr) + return ToUnderlyingTypeOrErr.takeError(); - return Importer.getToContext().getDecltypeType(ToExpr, UnderlyingType); + return Importer.getToContext().getDecltypeType( + *ToExprOrErr, *ToUnderlyingTypeOrErr); } -QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) { - QualType ToBaseType = Importer.Import(T->getBaseType()); - QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType()); - if (ToBaseType.isNull() || ToUnderlyingType.isNull()) - return {}; +ExpectedType +ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) { + ExpectedType ToBaseTypeOrErr = import(T->getBaseType()); + if (!ToBaseTypeOrErr) + return ToBaseTypeOrErr.takeError(); + + ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); + if (!ToUnderlyingTypeOrErr) + return ToUnderlyingTypeOrErr.takeError(); - return Importer.getToContext().getUnaryTransformType(ToBaseType, - ToUnderlyingType, - T->getUTTKind()); + return Importer.getToContext().getUnaryTransformType( + *ToBaseTypeOrErr, *ToUnderlyingTypeOrErr, T->getUTTKind()); } -QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { +ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) { // FIXME: Make sure that the "to" context supports C++11! - QualType FromDeduced = T->getDeducedType(); - QualType ToDeduced; - if (!FromDeduced.isNull()) { - ToDeduced = Importer.Import(FromDeduced); - if (ToDeduced.isNull()) - return {}; - } + ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType()); + if (!ToDeducedTypeOrErr) + return ToDeducedTypeOrErr.takeError(); - return Importer.getToContext().getAutoType(ToDeduced, T->getKeyword(), + return Importer.getToContext().getAutoType(*ToDeducedTypeOrErr, + T->getKeyword(), /*IsDependent*/false); } -QualType ASTNodeImporter::VisitInjectedClassNameType( +ExpectedType ASTNodeImporter::VisitInjectedClassNameType( const InjectedClassNameType *T) { - auto *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl())); - if (!D) - return {}; + Expected<CXXRecordDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); - QualType InjType = Importer.Import(T->getInjectedSpecializationType()); - if (InjType.isNull()) - return {}; + ExpectedType ToInjTypeOrErr = import(T->getInjectedSpecializationType()); + if (!ToInjTypeOrErr) + return ToInjTypeOrErr.takeError(); // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading // See comments in InjectedClassNameType definition for details @@ -951,220 +1341,208 @@ QualType ASTNodeImporter::VisitInjectedClassNameType( }; return QualType(new (Importer.getToContext(), TypeAlignment) - InjectedClassNameType(D, InjType), 0); + InjectedClassNameType(*ToDeclOrErr, *ToInjTypeOrErr), 0); } -QualType ASTNodeImporter::VisitRecordType(const RecordType *T) { - auto *ToDecl = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl())); - if (!ToDecl) - return {}; +ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) { + Expected<RecordDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); - return Importer.getToContext().getTagDeclType(ToDecl); + return Importer.getToContext().getTagDeclType(*ToDeclOrErr); } -QualType ASTNodeImporter::VisitEnumType(const EnumType *T) { - auto *ToDecl = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl())); - if (!ToDecl) - return {}; +ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) { + Expected<EnumDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); - return Importer.getToContext().getTagDeclType(ToDecl); + return Importer.getToContext().getTagDeclType(*ToDeclOrErr); } -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 {}; - } - if (!FromEquivalentType.isNull()) { - ToEquivalentType = Importer.Import(FromEquivalentType); - if (ToEquivalentType.isNull()) - return {}; - } +ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) { + ExpectedType ToModifiedTypeOrErr = import(T->getModifiedType()); + if (!ToModifiedTypeOrErr) + return ToModifiedTypeOrErr.takeError(); + ExpectedType ToEquivalentTypeOrErr = import(T->getEquivalentType()); + if (!ToEquivalentTypeOrErr) + return ToEquivalentTypeOrErr.takeError(); return Importer.getToContext().getAttributedType(T->getAttrKind(), - ToModifiedType, ToEquivalentType); + *ToModifiedTypeOrErr, *ToEquivalentTypeOrErr); } -QualType ASTNodeImporter::VisitTemplateTypeParmType( +ExpectedType ASTNodeImporter::VisitTemplateTypeParmType( const TemplateTypeParmType *T) { - auto *ParmDecl = - cast_or_null<TemplateTypeParmDecl>(Importer.Import(T->getDecl())); - if (!ParmDecl && T->getDecl()) - return {}; + Expected<TemplateTypeParmDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); return Importer.getToContext().getTemplateTypeParmType( - T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl); + T->getDepth(), T->getIndex(), T->isParameterPack(), *ToDeclOrErr); } -QualType ASTNodeImporter::VisitSubstTemplateTypeParmType( +ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType( const SubstTemplateTypeParmType *T) { - const auto *Replaced = - cast_or_null<TemplateTypeParmType>(Importer.Import( - QualType(T->getReplacedParameter(), 0)).getTypePtr()); - if (!Replaced) - return {}; + ExpectedType ReplacedOrErr = import(QualType(T->getReplacedParameter(), 0)); + if (!ReplacedOrErr) + return ReplacedOrErr.takeError(); + const TemplateTypeParmType *Replaced = + cast<TemplateTypeParmType>((*ReplacedOrErr).getTypePtr()); - QualType Replacement = Importer.Import(T->getReplacementType()); - if (Replacement.isNull()) - return {}; - Replacement = Replacement.getCanonicalType(); + ExpectedType ToReplacementTypeOrErr = import(T->getReplacementType()); + if (!ToReplacementTypeOrErr) + return ToReplacementTypeOrErr.takeError(); return Importer.getToContext().getSubstTemplateTypeParmType( - Replaced, Replacement); + Replaced, (*ToReplacementTypeOrErr).getCanonicalType()); } -QualType ASTNodeImporter::VisitTemplateSpecializationType( +ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { - TemplateName ToTemplate = Importer.Import(T->getTemplateName()); - if (ToTemplate.isNull()) - return {}; + auto ToTemplateOrErr = import(T->getTemplateName()); + if (!ToTemplateOrErr) + return ToTemplateOrErr.takeError(); SmallVector<TemplateArgument, 2> ToTemplateArgs; - if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToTemplateArgs)) - return {}; + if (Error Err = ImportTemplateArguments( + T->getArgs(), T->getNumArgs(), ToTemplateArgs)) + return std::move(Err); QualType ToCanonType; if (!QualType(T, 0).isCanonical()) { QualType FromCanonType = Importer.getFromContext().getCanonicalType(QualType(T, 0)); - ToCanonType =Importer.Import(FromCanonType); - if (ToCanonType.isNull()) - return {}; + if (ExpectedType TyOrErr = import(FromCanonType)) + ToCanonType = *TyOrErr; + else + return TyOrErr.takeError(); } - return Importer.getToContext().getTemplateSpecializationType(ToTemplate, + return Importer.getToContext().getTemplateSpecializationType(*ToTemplateOrErr, ToTemplateArgs, ToCanonType); } -QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) { - NestedNameSpecifier *ToQualifier = nullptr; +ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) { // Note: the qualifier in an ElaboratedType is optional. - if (T->getQualifier()) { - ToQualifier = Importer.Import(T->getQualifier()); - if (!ToQualifier) - return {}; - } + auto ToQualifierOrErr = import(T->getQualifier()); + if (!ToQualifierOrErr) + return ToQualifierOrErr.takeError(); - QualType ToNamedType = Importer.Import(T->getNamedType()); - if (ToNamedType.isNull()) - return {}; + ExpectedType ToNamedTypeOrErr = import(T->getNamedType()); + if (!ToNamedTypeOrErr) + return ToNamedTypeOrErr.takeError(); - TagDecl *OwnedTagDecl = - cast_or_null<TagDecl>(Importer.Import(T->getOwnedTagDecl())); - if (!OwnedTagDecl && T->getOwnedTagDecl()) - return {}; + Expected<TagDecl *> ToOwnedTagDeclOrErr = import(T->getOwnedTagDecl()); + if (!ToOwnedTagDeclOrErr) + return ToOwnedTagDeclOrErr.takeError(); return Importer.getToContext().getElaboratedType(T->getKeyword(), - ToQualifier, ToNamedType, - OwnedTagDecl); + *ToQualifierOrErr, + *ToNamedTypeOrErr, + *ToOwnedTagDeclOrErr); } -QualType ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) { - QualType Pattern = Importer.Import(T->getPattern()); - if (Pattern.isNull()) - return {}; +ExpectedType +ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) { + ExpectedType ToPatternOrErr = import(T->getPattern()); + if (!ToPatternOrErr) + return ToPatternOrErr.takeError(); - return Importer.getToContext().getPackExpansionType(Pattern, + return Importer.getToContext().getPackExpansionType(*ToPatternOrErr, T->getNumExpansions()); } -QualType ASTNodeImporter::VisitDependentTemplateSpecializationType( +ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType( const DependentTemplateSpecializationType *T) { - NestedNameSpecifier *Qualifier = Importer.Import(T->getQualifier()); - if (!Qualifier && T->getQualifier()) - return {}; + auto ToQualifierOrErr = import(T->getQualifier()); + if (!ToQualifierOrErr) + return ToQualifierOrErr.takeError(); - IdentifierInfo *Name = Importer.Import(T->getIdentifier()); - if (!Name && T->getIdentifier()) - return {}; + IdentifierInfo *ToName = Importer.Import(T->getIdentifier()); SmallVector<TemplateArgument, 2> ToPack; ToPack.reserve(T->getNumArgs()); - if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToPack)) - return {}; + if (Error Err = ImportTemplateArguments( + T->getArgs(), T->getNumArgs(), ToPack)) + return std::move(Err); return Importer.getToContext().getDependentTemplateSpecializationType( - T->getKeyword(), Qualifier, Name, ToPack); + T->getKeyword(), *ToQualifierOrErr, ToName, ToPack); } -QualType ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) { - NestedNameSpecifier *NNS = Importer.Import(T->getQualifier()); - if (!NNS && T->getQualifier()) - return QualType(); +ExpectedType +ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) { + auto ToQualifierOrErr = import(T->getQualifier()); + if (!ToQualifierOrErr) + return ToQualifierOrErr.takeError(); IdentifierInfo *Name = Importer.Import(T->getIdentifier()); - if (!Name && T->getIdentifier()) - return QualType(); - QualType Canon = (T == T->getCanonicalTypeInternal().getTypePtr()) - ? QualType() - : Importer.Import(T->getCanonicalTypeInternal()); - if (!Canon.isNull()) - Canon = Canon.getCanonicalType(); + QualType Canon; + if (T != T->getCanonicalTypeInternal().getTypePtr()) { + if (ExpectedType TyOrErr = import(T->getCanonicalTypeInternal())) + Canon = (*TyOrErr).getCanonicalType(); + else + return TyOrErr.takeError(); + } - return Importer.getToContext().getDependentNameType(T->getKeyword(), NNS, + return Importer.getToContext().getDependentNameType(T->getKeyword(), + *ToQualifierOrErr, Name, Canon); } -QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { - auto *Class = - dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl())); - if (!Class) - return {}; +ExpectedType +ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { + Expected<ObjCInterfaceDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); - return Importer.getToContext().getObjCInterfaceType(Class); + return Importer.getToContext().getObjCInterfaceType(*ToDeclOrErr); } -QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) { - QualType ToBaseType = Importer.Import(T->getBaseType()); - if (ToBaseType.isNull()) - return {}; +ExpectedType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) { + ExpectedType ToBaseTypeOrErr = import(T->getBaseType()); + if (!ToBaseTypeOrErr) + return ToBaseTypeOrErr.takeError(); SmallVector<QualType, 4> TypeArgs; for (auto TypeArg : T->getTypeArgsAsWritten()) { - QualType ImportedTypeArg = Importer.Import(TypeArg); - if (ImportedTypeArg.isNull()) - return {}; - - TypeArgs.push_back(ImportedTypeArg); + if (ExpectedType TyOrErr = import(TypeArg)) + TypeArgs.push_back(*TyOrErr); + else + return TyOrErr.takeError(); } SmallVector<ObjCProtocolDecl *, 4> Protocols; for (auto *P : T->quals()) { - auto *Protocol = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(P)); - if (!Protocol) - return {}; - Protocols.push_back(Protocol); + if (Expected<ObjCProtocolDecl *> ProtocolOrErr = import(P)) + Protocols.push_back(*ProtocolOrErr); + else + return ProtocolOrErr.takeError(); + } - return Importer.getToContext().getObjCObjectType(ToBaseType, TypeArgs, + return Importer.getToContext().getObjCObjectType(*ToBaseTypeOrErr, TypeArgs, Protocols, T->isKindOfTypeAsWritten()); } -QualType +ExpectedType ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { - QualType ToPointeeType = Importer.Import(T->getPointeeType()); - if (ToPointeeType.isNull()) - return {}; + ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); + if (!ToPointeeTypeOrErr) + return ToPointeeTypeOrErr.takeError(); - return Importer.getToContext().getObjCObjectPointerType(ToPointeeType); + return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr); } //---------------------------------------------------------------------------- // Import Declarations //---------------------------------------------------------------------------- -bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC, - DeclContext *&LexicalDC, - DeclarationName &Name, - NamedDecl *&ToD, - SourceLocation &Loc) { +Error ASTNodeImporter::ImportDeclParts( + NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, + DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) { // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop. // example: int struct_in_proto(struct data_t{int a;int b;} *d); DeclContext *OrigDC = D->getDeclContext(); @@ -1184,66 +1562,66 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC, if (RT && RT->getDecl() == D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return true; + return make_error<ImportError>(ImportError::UnsupportedConstruct); } } } // Import the context of this declaration. - DC = Importer.ImportContext(OrigDC); - if (!DC) - return true; - - LexicalDC = DC; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return true; - } + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return Err; // Import the name of this declaration. - Name = Importer.Import(D->getDeclName()); - if (D->getDeclName() && !Name) - return true; + if (Error Err = importInto(Name, D->getDeclName())) + return Err; // Import the location of this declaration. - Loc = Importer.Import(D->getLocation()); + if (Error Err = importInto(Loc, D->getLocation())) + return Err; + ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D)); - return false; + if (ToD) + if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD)) + return Err; + + return Error::success(); } -void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { +Error ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { if (!FromD) - return; - - if (!ToD) { - ToD = Importer.Import(FromD); - if (!ToD) - return; - } + return Error::success(); - if (auto *FromRecord = dyn_cast<RecordDecl>(FromD)) { - if (auto *ToRecord = cast_or_null<RecordDecl>(ToD)) { - if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && !ToRecord->getDefinition()) { - ImportDefinition(FromRecord, ToRecord); + if (!ToD) + if (Error Err = importInto(ToD, FromD)) + return Err; + + if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) { + if (RecordDecl *ToRecord = cast<RecordDecl>(ToD)) { + if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && + !ToRecord->getDefinition()) { + if (Error Err = ImportDefinition(FromRecord, ToRecord)) + return Err; } } - return; + return Error::success(); } - if (auto *FromEnum = dyn_cast<EnumDecl>(FromD)) { - if (auto *ToEnum = cast_or_null<EnumDecl>(ToD)) { + if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) { + if (EnumDecl *ToEnum = cast<EnumDecl>(ToD)) { if (FromEnum->getDefinition() && !ToEnum->getDefinition()) { - ImportDefinition(FromEnum, ToEnum); + if (Error Err = ImportDefinition(FromEnum, ToEnum)) + return Err; } } - return; + return Error::success(); } + + return Error::success(); } -void -ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, - DeclarationNameInfo& To) { +Error +ASTNodeImporter::ImportDeclarationNameLoc( + const DeclarationNameInfo &From, DeclarationNameInfo& To) { // NOTE: To.Name and To.Loc are already imported. // We only have to import To.LocInfo. switch (To.getName().getNameKind()) { @@ -1253,76 +1631,121 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, case DeclarationName::ObjCMultiArgSelector: case DeclarationName::CXXUsingDirective: case DeclarationName::CXXDeductionGuideName: - return; + return Error::success(); case DeclarationName::CXXOperatorName: { - SourceRange Range = From.getCXXOperatorNameRange(); - To.setCXXOperatorNameRange(Importer.Import(Range)); - return; + if (auto ToRangeOrErr = import(From.getCXXOperatorNameRange())) + To.setCXXOperatorNameRange(*ToRangeOrErr); + else + return ToRangeOrErr.takeError(); + return Error::success(); } case DeclarationName::CXXLiteralOperatorName: { - SourceLocation Loc = From.getCXXLiteralOperatorNameLoc(); - To.setCXXLiteralOperatorNameLoc(Importer.Import(Loc)); - return; + if (ExpectedSLoc LocOrErr = import(From.getCXXLiteralOperatorNameLoc())) + To.setCXXLiteralOperatorNameLoc(*LocOrErr); + else + return LocOrErr.takeError(); + return Error::success(); } case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: { - TypeSourceInfo *FromTInfo = From.getNamedTypeInfo(); - To.setNamedTypeInfo(Importer.Import(FromTInfo)); - return; + if (auto ToTInfoOrErr = import(From.getNamedTypeInfo())) + To.setNamedTypeInfo(*ToTInfoOrErr); + else + return ToTInfoOrErr.takeError(); + return Error::success(); } } llvm_unreachable("Unknown name kind."); } -void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { +Error +ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { if (Importer.isMinimalImport() && !ForceImport) { - Importer.ImportContext(FromDC); - return; + auto ToDCOrErr = Importer.ImportContext(FromDC); + return ToDCOrErr.takeError(); } + llvm::SmallVector<Decl *, 8> ImportedDecls; + for (auto *From : FromDC->decls()) { + ExpectedDecl ImportedOrErr = import(From); + if (!ImportedOrErr) + // Ignore the error, continue with next Decl. + // FIXME: Handle this case somehow better. + consumeError(ImportedOrErr.takeError()); + } + + return Error::success(); +} + +Error ASTNodeImporter::ImportDeclContext( + Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) { + auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext()); + if (!ToDCOrErr) + return ToDCOrErr.takeError(); + ToDC = *ToDCOrErr; + + if (FromD->getDeclContext() != FromD->getLexicalDeclContext()) { + auto ToLexicalDCOrErr = Importer.ImportContext( + FromD->getLexicalDeclContext()); + if (!ToLexicalDCOrErr) + return ToLexicalDCOrErr.takeError(); + ToLexicalDC = *ToLexicalDCOrErr; + } else + ToLexicalDC = ToDC; - for (auto *From : FromDC->decls()) - Importer.Import(From); + return Error::success(); } -void ASTNodeImporter::ImportImplicitMethods( +Error ASTNodeImporter::ImportImplicitMethods( const CXXRecordDecl *From, CXXRecordDecl *To) { assert(From->isCompleteDefinition() && To->getDefinition() == To && "Import implicit methods to or from non-definition"); for (CXXMethodDecl *FromM : From->methods()) - if (FromM->isImplicit()) - Importer.Import(FromM); + if (FromM->isImplicit()) { + Expected<CXXMethodDecl *> ToMOrErr = import(FromM); + if (!ToMOrErr) + return ToMOrErr.takeError(); + } + + return Error::success(); } -static void setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To, - ASTImporter &Importer) { +static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To, + ASTImporter &Importer) { if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) { - auto *ToTypedef = - cast_or_null<TypedefNameDecl>(Importer.Import(FromTypedef)); - assert (ToTypedef && "Failed to import typedef of an anonymous structure"); - - To->setTypedefNameForAnonDecl(ToTypedef); + Decl *ToTypedef = Importer.Import(FromTypedef); + if (!ToTypedef) + return make_error<ImportError>(); + To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(ToTypedef)); + // FIXME: This should be the final code. + //if (Expected<Decl *> ToTypedefOrErr = Importer.Import(FromTypedef)) + // To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(*ToTypedefOrErr)); + //else + // return ToTypedefOrErr.takeError(); } + return Error::success(); } -bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, - ImportDefinitionKind Kind) { +Error ASTNodeImporter::ImportDefinition( + RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) { if (To->getDefinition() || To->isBeingDefined()) { if (Kind == IDK_Everything) - ImportDeclContext(From, /*ForceImport=*/true); + return ImportDeclContext(From, /*ForceImport=*/true); - return false; + return Error::success(); } To->startDefinition(); - setTypedefNameForAnonDecl(From, To, Importer); + if (Error Err = setTypedefNameForAnonDecl(From, To, Importer)) + return Err; // Add base classes. - if (auto *ToCXX = dyn_cast<CXXRecordDecl>(To)) { - auto *FromCXX = cast<CXXRecordDecl>(From); + auto *ToCXX = dyn_cast<CXXRecordDecl>(To); + auto *FromCXX = dyn_cast<CXXRecordDecl>(From); + if (ToCXX && FromCXX && ToCXX->dataPtr() && FromCXX->dataPtr()) { struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data(); struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data(); @@ -1394,50 +1817,65 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, SmallVector<CXXBaseSpecifier *, 4> Bases; for (const auto &Base1 : FromCXX->bases()) { - QualType T = Importer.Import(Base1.getType()); - if (T.isNull()) - return true; + ExpectedType TyOrErr = import(Base1.getType()); + if (!TyOrErr) + return TyOrErr.takeError(); SourceLocation EllipsisLoc; - if (Base1.isPackExpansion()) - EllipsisLoc = Importer.Import(Base1.getEllipsisLoc()); + if (Base1.isPackExpansion()) { + if (ExpectedSLoc LocOrErr = import(Base1.getEllipsisLoc())) + EllipsisLoc = *LocOrErr; + else + return LocOrErr.takeError(); + } // Ensure that we have a definition for the base. - ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl()); + if (Error Err = + ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl())) + return Err; + + auto RangeOrErr = import(Base1.getSourceRange()); + if (!RangeOrErr) + return RangeOrErr.takeError(); + + auto TSIOrErr = import(Base1.getTypeSourceInfo()); + if (!TSIOrErr) + return TSIOrErr.takeError(); Bases.push_back( - new (Importer.getToContext()) - CXXBaseSpecifier(Importer.Import(Base1.getSourceRange()), - Base1.isVirtual(), - Base1.isBaseOfClass(), - Base1.getAccessSpecifierAsWritten(), - Importer.Import(Base1.getTypeSourceInfo()), - EllipsisLoc)); + new (Importer.getToContext()) CXXBaseSpecifier( + *RangeOrErr, + Base1.isVirtual(), + Base1.isBaseOfClass(), + Base1.getAccessSpecifierAsWritten(), + *TSIOrErr, + EllipsisLoc)); } if (!Bases.empty()) ToCXX->setBases(Bases.data(), Bases.size()); } if (shouldForceImportDeclContext(Kind)) - ImportDeclContext(From, /*ForceImport=*/true); + if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) + return Err; To->completeDefinition(); - return false; + return Error::success(); } -bool ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) { +Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) { if (To->getAnyInitializer()) - return false; + return Error::success(); Expr *FromInit = From->getInit(); if (!FromInit) - return false; + return Error::success(); - Expr *ToInit = Importer.Import(const_cast<Expr *>(FromInit)); - if (!ToInit) - return true; + ExpectedExpr ToInitOrErr = import(FromInit); + if (!ToInitOrErr) + return ToInitOrErr.takeError(); - To->setInit(ToInit); + To->setInit(*ToInitOrErr); if (From->isInitKnownICE()) { EvaluatedStmt *Eval = To->ensureEvaluatedStmt(); Eval->CheckedICE = true; @@ -1445,185 +1883,106 @@ bool ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) { } // FIXME: Other bits to merge? - return false; + return Error::success(); } -bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, - ImportDefinitionKind Kind) { +Error ASTNodeImporter::ImportDefinition( + EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind) { if (To->getDefinition() || To->isBeingDefined()) { if (Kind == IDK_Everything) - ImportDeclContext(From, /*ForceImport=*/true); - return false; + return ImportDeclContext(From, /*ForceImport=*/true); + return Error::success(); } To->startDefinition(); - setTypedefNameForAnonDecl(From, To, Importer); + if (Error Err = setTypedefNameForAnonDecl(From, To, Importer)) + return Err; - QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(From)); - if (T.isNull()) - return true; + ExpectedType ToTypeOrErr = + import(Importer.getFromContext().getTypeDeclType(From)); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - QualType ToPromotionType = Importer.Import(From->getPromotionType()); - if (ToPromotionType.isNull()) - return true; + ExpectedType ToPromotionTypeOrErr = import(From->getPromotionType()); + if (!ToPromotionTypeOrErr) + return ToPromotionTypeOrErr.takeError(); if (shouldForceImportDeclContext(Kind)) - ImportDeclContext(From, /*ForceImport=*/true); + if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) + return Err; // FIXME: we might need to merge the number of positive or negative bits // if the enumerator lists don't match. - To->completeDefinition(T, ToPromotionType, + To->completeDefinition(*ToTypeOrErr, *ToPromotionTypeOrErr, From->getNumPositiveBits(), From->getNumNegativeBits()); - return false; + return Error::success(); } -TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( - TemplateParameterList *Params) { +// FIXME: Remove this, use `import` instead. +Expected<TemplateParameterList *> ASTNodeImporter::ImportTemplateParameterList( + TemplateParameterList *Params) { SmallVector<NamedDecl *, 4> ToParams(Params->size()); - if (ImportContainerChecked(*Params, ToParams)) - return nullptr; + if (Error Err = ImportContainerChecked(*Params, ToParams)) + return std::move(Err); Expr *ToRequiresClause; if (Expr *const R = Params->getRequiresClause()) { - ToRequiresClause = Importer.Import(R); - if (!ToRequiresClause) - return nullptr; + if (Error Err = importInto(ToRequiresClause, R)) + return std::move(Err); } else { ToRequiresClause = nullptr; } - return TemplateParameterList::Create(Importer.getToContext(), - Importer.Import(Params->getTemplateLoc()), - Importer.Import(Params->getLAngleLoc()), - ToParams, - Importer.Import(Params->getRAngleLoc()), - ToRequiresClause); -} - -TemplateArgument -ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { - switch (From.getKind()) { - case TemplateArgument::Null: - return TemplateArgument(); - - case TemplateArgument::Type: { - QualType ToType = Importer.Import(From.getAsType()); - if (ToType.isNull()) - return {}; - return TemplateArgument(ToType); - } - - case TemplateArgument::Integral: { - QualType ToType = Importer.Import(From.getIntegralType()); - if (ToType.isNull()) - return {}; - return TemplateArgument(From, ToType); - } - - case TemplateArgument::Declaration: { - auto *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl())); - QualType ToType = Importer.Import(From.getParamTypeForDecl()); - if (!To || ToType.isNull()) - return {}; - return TemplateArgument(To, ToType); - } - - case TemplateArgument::NullPtr: { - QualType ToType = Importer.Import(From.getNullPtrType()); - if (ToType.isNull()) - return {}; - return TemplateArgument(ToType, /*isNullPtr*/true); - } - - case TemplateArgument::Template: { - TemplateName ToTemplate = Importer.Import(From.getAsTemplate()); - if (ToTemplate.isNull()) - return {}; - - return TemplateArgument(ToTemplate); - } - - case TemplateArgument::TemplateExpansion: { - TemplateName ToTemplate - = Importer.Import(From.getAsTemplateOrTemplatePattern()); - if (ToTemplate.isNull()) - return {}; - - return TemplateArgument(ToTemplate, From.getNumTemplateExpansions()); - } - - case TemplateArgument::Expression: - if (Expr *ToExpr = Importer.Import(From.getAsExpr())) - return TemplateArgument(ToExpr); - return TemplateArgument(); - - case TemplateArgument::Pack: { - SmallVector<TemplateArgument, 2> ToPack; - ToPack.reserve(From.pack_size()); - if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack)) - return {}; - - return TemplateArgument( - llvm::makeArrayRef(ToPack).copy(Importer.getToContext())); - } - } - - llvm_unreachable("Invalid template argument kind"); -} - -Optional<TemplateArgumentLoc> -ASTNodeImporter::ImportTemplateArgumentLoc(const TemplateArgumentLoc &TALoc) { - TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument()); - TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); - TemplateArgumentLocInfo ToInfo; - if (Arg.getKind() == TemplateArgument::Expression) { - Expr *E = Importer.Import(FromInfo.getAsExpr()); - ToInfo = TemplateArgumentLocInfo(E); - if (!E) - return None; - } else if (Arg.getKind() == TemplateArgument::Type) { - if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo())) - ToInfo = TemplateArgumentLocInfo(TSI); + auto ToTemplateLocOrErr = import(Params->getTemplateLoc()); + if (!ToTemplateLocOrErr) + return ToTemplateLocOrErr.takeError(); + auto ToLAngleLocOrErr = import(Params->getLAngleLoc()); + if (!ToLAngleLocOrErr) + return ToLAngleLocOrErr.takeError(); + auto ToRAngleLocOrErr = import(Params->getRAngleLoc()); + if (!ToRAngleLocOrErr) + return ToRAngleLocOrErr.takeError(); + + return TemplateParameterList::Create( + Importer.getToContext(), + *ToTemplateLocOrErr, + *ToLAngleLocOrErr, + ToParams, + *ToRAngleLocOrErr, + ToRequiresClause); +} + +Error ASTNodeImporter::ImportTemplateArguments( + const TemplateArgument *FromArgs, unsigned NumFromArgs, + SmallVectorImpl<TemplateArgument> &ToArgs) { + for (unsigned I = 0; I != NumFromArgs; ++I) { + if (auto ToOrErr = import(FromArgs[I])) + ToArgs.push_back(*ToOrErr); else - return None; - } else { - ToInfo = TemplateArgumentLocInfo( - Importer.Import(FromInfo.getTemplateQualifierLoc()), - Importer.Import(FromInfo.getTemplateNameLoc()), - Importer.Import(FromInfo.getTemplateEllipsisLoc())); + return ToOrErr.takeError(); } - return TemplateArgumentLoc(Arg, ToInfo); -} -bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, - unsigned NumFromArgs, - SmallVectorImpl<TemplateArgument> &ToArgs) { - for (unsigned I = 0; I != NumFromArgs; ++I) { - TemplateArgument To = ImportTemplateArgument(FromArgs[I]); - if (To.isNull() && !FromArgs[I].isNull()) - return true; - - ToArgs.push_back(To); - } + return Error::success(); +} - return false; +// FIXME: Do not forget to remove this and use only 'import'. +Expected<TemplateArgument> +ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { + return import(From); } -// We cannot use Optional<> pattern here and below because -// TemplateArgumentListInfo's operator new is declared as deleted so it cannot -// be stored in Optional. template <typename InContainerTy> -bool ASTNodeImporter::ImportTemplateArgumentListInfo( +Error ASTNodeImporter::ImportTemplateArgumentListInfo( const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) { for (const auto &FromLoc : Container) { - if (auto ToLoc = ImportTemplateArgumentLoc(FromLoc)) - ToTAInfo.addArgument(*ToLoc); + if (auto ToLocOrErr = import(FromLoc)) + ToTAInfo.addArgument(*ToLocOrErr); else - return true; + return ToLocOrErr.takeError(); } - return false; + return Error::success(); } static StructuralEquivalenceKind @@ -1720,30 +2079,31 @@ bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, return Ctx.IsEquivalent(From, To); } -Decl *ASTNodeImporter::VisitDecl(Decl *D) { +ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return nullptr; + return make_error<ImportError>(ImportError::UnsupportedConstruct); } -Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { - // Import the context of this declaration. - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - if (!DC) - return nullptr; +ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { + Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) + << D->getDeclKindName(); + return make_error<ImportError>(ImportError::UnsupportedConstruct); +} - DeclContext *LexicalDC = DC; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return nullptr; - } +ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { + // Import the context of this declaration. + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); + ExpectedSLoc LocOrErr = import(D->getLocation()); + if (!LocOrErr) + return LocOrErr.takeError(); EmptyDecl *ToD; - if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc)) + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, *LocOrErr)) return ToD; ToD->setLexicalDeclContext(LexicalDC); @@ -1751,7 +2111,7 @@ Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { return ToD; } -Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { +ExpectedDecl ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); @@ -1760,18 +2120,23 @@ Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { return ToD; } -Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { - SourceLocation Loc = Importer.Import(D->getLocation()); - SourceLocation ColonLoc = Importer.Import(D->getColonLoc()); +ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { + ExpectedSLoc LocOrErr = import(D->getLocation()); + if (!LocOrErr) + return LocOrErr.takeError(); + auto ColonLocOrErr = import(D->getColonLoc()); + if (!ColonLocOrErr) + return ColonLocOrErr.takeError(); // Import the context of this declaration. - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - if (!DC) - return nullptr; + auto DCOrErr = Importer.ImportContext(D->getDeclContext()); + if (!DCOrErr) + return DCOrErr.takeError(); + DeclContext *DC = *DCOrErr; AccessSpecDecl *ToD; if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(), - DC, Loc, ColonLoc)) + DC, *LocOrErr, *ColonLocOrErr)) return ToD; // Lexical DeclContext and Semantic DeclContext @@ -1782,29 +2147,26 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { return ToD; } -Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - if (!DC) - return nullptr; - +ExpectedDecl ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { + auto DCOrErr = Importer.ImportContext(D->getDeclContext()); + if (!DCOrErr) + return DCOrErr.takeError(); + DeclContext *DC = *DCOrErr; DeclContext *LexicalDC = DC; - // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); - - Expr *AssertExpr = Importer.Import(D->getAssertExpr()); - if (!AssertExpr) - return nullptr; - - StringLiteral *FromMsg = D->getMessage(); - auto *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg)); - if (!ToMsg && FromMsg) - return nullptr; + SourceLocation ToLocation, ToRParenLoc; + Expr *ToAssertExpr; + StringLiteral *ToMessage; + if (auto Imp = importSeq( + D->getLocation(), D->getAssertExpr(), D->getMessage(), D->getRParenLoc())) + std::tie(ToLocation, ToAssertExpr, ToMessage, ToRParenLoc) = *Imp; + else + return Imp.takeError(); StaticAssertDecl *ToD; if (GetImportedOrCreateDecl( - ToD, D, Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, - Importer.Import(D->getRParenLoc()), D->isFailed())) + ToD, D, Importer.getToContext(), DC, ToLocation, ToAssertExpr, ToMessage, + ToRParenLoc, D->isFailed())) return ToD; ToD->setLexicalDeclContext(LexicalDC); @@ -1812,14 +2174,14 @@ Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { return ToD; } -Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { +ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Import the major distinguishing characteristics of this namespace. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -1853,15 +2215,21 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Namespace, ConflictingDecls.data(), ConflictingDecls.size()); + if (!Name) + return make_error<ImportError>(ImportError::NameConflict); } } + ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + // Create the "to" namespace, if needed. NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { if (GetImportedOrCreateDecl( ToNamespace, D, Importer.getToContext(), DC, D->isInline(), - Importer.Import(D->getBeginLoc()), Loc, Name.getAsIdentifierInfo(), + *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), /*PrevDecl=*/nullptr)) return ToNamespace; ToNamespace->setLexicalDeclContext(LexicalDC); @@ -1878,43 +2246,42 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { } Importer.MapImported(D, ToNamespace); - ImportDeclContext(D); + if (Error Err = ImportDeclContext(D)) + return std::move(Err); return ToNamespace; } -Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { +ExpectedDecl ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { // Import the major distinguishing characteristics of this namespace. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *LookupD; - if (ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc)) + return std::move(Err); if (LookupD) return LookupD; // NOTE: No conflict resolution is done for namespace aliases now. - auto *TargetDecl = cast_or_null<NamespaceDecl>( - Importer.Import(D->getNamespace())); - if (!TargetDecl) - return nullptr; - - IdentifierInfo *ToII = Importer.Import(D->getIdentifier()); - if (!ToII) - return nullptr; - - NestedNameSpecifierLoc ToQLoc = Importer.Import(D->getQualifierLoc()); - if (D->getQualifierLoc() && !ToQLoc) - return nullptr; + SourceLocation ToNamespaceLoc, ToAliasLoc, ToTargetNameLoc; + NestedNameSpecifierLoc ToQualifierLoc; + NamespaceDecl *ToNamespace; + if (auto Imp = importSeq( + D->getNamespaceLoc(), D->getAliasLoc(), D->getQualifierLoc(), + D->getTargetNameLoc(), D->getNamespace())) + std::tie( + ToNamespaceLoc, ToAliasLoc, ToQualifierLoc, ToTargetNameLoc, + ToNamespace) = *Imp; + else + return Imp.takeError(); + IdentifierInfo *ToIdentifier = Importer.Import(D->getIdentifier()); NamespaceAliasDecl *ToD; - if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, - Importer.Import(D->getNamespaceLoc()), - Importer.Import(D->getAliasLoc()), ToII, ToQLoc, - Importer.Import(D->getTargetNameLoc()), - TargetDecl)) + if (GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), DC, ToNamespaceLoc, ToAliasLoc, + ToIdentifier, ToQualifierLoc, ToTargetNameLoc, ToNamespace)) return ToD; ToD->setLexicalDeclContext(LexicalDC); @@ -1923,14 +2290,15 @@ Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { return ToD; } -Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { +ExpectedDecl +ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -1946,9 +2314,16 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) { - if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), - FoundTypedef->getUnderlyingType())) - return Importer.MapImported(D, FoundTypedef); + QualType FromUT = D->getUnderlyingType(); + QualType FoundUT = FoundTypedef->getUnderlyingType(); + if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) { + // If the "From" context has a complete underlying type but we + // already have a complete underlying type then return with that. + if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType()) + return Importer.MapImported(D, FoundTypedef); + } + // FIXME Handle redecl chain. + break; } ConflictingDecls.push_back(FoundDecl); @@ -1959,28 +2334,30 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return nullptr; + return make_error<ImportError>(ImportError::NameConflict); } } - // Import the underlying type of this typedef; - QualType T = Importer.Import(D->getUnderlyingType()); - if (T.isNull()) - return nullptr; + QualType ToUnderlyingType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToBeginLoc; + if (auto Imp = importSeq( + D->getUnderlyingType(), D->getTypeSourceInfo(), D->getBeginLoc())) + std::tie(ToUnderlyingType, ToTypeSourceInfo, ToBeginLoc) = *Imp; + else + return Imp.takeError(); // Create the new typedef node. - TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - SourceLocation StartL = Importer.Import(D->getBeginLoc()); - + // FIXME: ToUnderlyingType is not used. TypedefNameDecl *ToTypedef; if (IsAlias) { if (GetImportedOrCreateDecl<TypeAliasDecl>( - ToTypedef, D, Importer.getToContext(), DC, StartL, Loc, - Name.getAsIdentifierInfo(), TInfo)) + ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc, + Name.getAsIdentifierInfo(), ToTypeSourceInfo)) return ToTypedef; } else if (GetImportedOrCreateDecl<TypedefDecl>( - ToTypedef, D, Importer.getToContext(), DC, StartL, Loc, - Name.getAsIdentifierInfo(), TInfo)) + ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc, + Name.getAsIdentifierInfo(), ToTypeSourceInfo)) return ToTypedef; ToTypedef->setAccess(D->getAccess()); @@ -1994,22 +2371,23 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { return ToTypedef; } -Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { +ExpectedDecl ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { return VisitTypedefNameDecl(D, /*IsAlias=*/false); } -Decl *ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) { +ExpectedDecl ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) { return VisitTypedefNameDecl(D, /*IsAlias=*/true); } -Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { +ExpectedDecl +ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { // Import the major distinguishing characteristics of this typedef. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *FoundD; - if (ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc)) + return std::move(Err); if (FoundD) return FoundD; @@ -2034,26 +2412,23 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return nullptr; + return make_error<ImportError>(ImportError::NameConflict); } } - TemplateParameterList *Params = ImportTemplateParameterList( - D->getTemplateParameters()); - if (!Params) - return nullptr; - - auto *TemplDecl = cast_or_null<TypeAliasDecl>( - Importer.Import(D->getTemplatedDecl())); - if (!TemplDecl) - return nullptr; + TemplateParameterList *ToTemplateParameters; + TypeAliasDecl *ToTemplatedDecl; + if (auto Imp = importSeq(D->getTemplateParameters(), D->getTemplatedDecl())) + std::tie(ToTemplateParameters, ToTemplatedDecl) = *Imp; + else + return Imp.takeError(); TypeAliasTemplateDecl *ToAlias; if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc, - Name, Params, TemplDecl)) + Name, ToTemplateParameters, ToTemplatedDecl)) return ToAlias; - TemplDecl->setDescribedAliasTemplate(ToAlias); + ToTemplatedDecl->setDescribedAliasTemplate(ToAlias); ToAlias->setAccess(D->getAccess()); ToAlias->setLexicalDeclContext(LexicalDC); @@ -2061,48 +2436,53 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { return ToAlias; } -Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { +ExpectedDecl ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { // Import the major distinguishing characteristics of this label. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; assert(LexicalDC->isFunctionOrMethod()); LabelDecl *ToLabel; - if (D->isGnuLocal() - ? GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, - Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo(), - Importer.Import(D->getBeginLoc())) - : GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, - Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo())) - return ToLabel; - - auto *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt())); - if (!Label) - return nullptr; + if (D->isGnuLocal()) { + ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), *BeginLocOrErr)) + return ToLabel; - ToLabel->setStmt(Label); + } else { + if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo())) + return ToLabel; + + } + + Expected<LabelStmt *> ToStmtOrErr = import(D->getStmt()); + if (!ToStmtOrErr) + return ToStmtOrErr.takeError(); + + ToLabel->setStmt(*ToStmtOrErr); ToLabel->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToLabel); return ToLabel; } -Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { +ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Import the major distinguishing characteristics of this enum. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -2110,7 +2490,9 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; if (!SearchName && D->getTypedefNameForAnonDecl()) { - SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName()); + if (Error Err = importInto( + SearchName, D->getTypedefNameForAnonDecl()->getDeclName())) + return std::move(Err); IDNS = Decl::IDNS_Ordinary; } else if (Importer.getToContext().getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; @@ -2124,13 +2506,12 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - Decl *Found = FoundDecl; - if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) { + if (auto *Typedef = dyn_cast<TypedefNameDecl>(FoundDecl)) { if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) - Found = Tag->getDecl(); + FoundDecl = Tag->getDecl(); } - if (auto *FoundEnum = dyn_cast<EnumDecl>(Found)) { + if (auto *FoundEnum = dyn_cast<EnumDecl>(FoundDecl)) { if (IsStructuralMatch(D, FoundEnum)) return Importer.MapImported(D, FoundEnum); } @@ -2142,37 +2523,43 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { Name = Importer.HandleNameConflict(Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); + if (!Name) + return make_error<ImportError>(ImportError::NameConflict); } } + SourceLocation ToBeginLoc; + NestedNameSpecifierLoc ToQualifierLoc; + QualType ToIntegerType; + if (auto Imp = importSeq( + D->getBeginLoc(), D->getQualifierLoc(), D->getIntegerType())) + std::tie(ToBeginLoc, ToQualifierLoc, ToIntegerType) = *Imp; + else + return Imp.takeError(); + // Create the enum declaration. EnumDecl *D2; if (GetImportedOrCreateDecl( - D2, D, Importer.getToContext(), DC, Importer.Import(D->getBeginLoc()), + D2, D, Importer.getToContext(), DC, ToBeginLoc, Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed())) return D2; - // Import the qualifier, if any. - D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); + D2->setQualifierInfo(ToQualifierLoc); + D2->setIntegerType(ToIntegerType); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); - // Import the integer type. - QualType ToIntegerType = Importer.Import(D->getIntegerType()); - if (ToIntegerType.isNull()) - return nullptr; - D2->setIntegerType(ToIntegerType); - // Import the definition - if (D->isCompleteDefinition() && ImportDefinition(D, D2)) - return nullptr; + if (D->isCompleteDefinition()) + if (Error Err = ImportDefinition(D, D2)) + return std::move(Err); return D2; } -Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { +ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { bool IsFriendTemplate = false; if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { IsFriendTemplate = @@ -2194,11 +2581,11 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // ClassTemplateSpecializationDecl itself. Thus, we start with an extra // condition in order to be able to import the implict Decl. !D->isImplicit()) { - Decl *ImportedDef = Importer.Import(Definition); - if (!ImportedDef) - return nullptr; + ExpectedDecl ImportedDefOrErr = import(Definition); + if (!ImportedDefOrErr) + return ImportedDefOrErr.takeError(); - return Importer.MapImported(D, ImportedDef); + return Importer.MapImported(D, *ImportedDefOrErr); } // Import the major distinguishing characteristics of this record. @@ -2206,8 +2593,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -2215,7 +2602,9 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; if (!SearchName && D->getTypedefNameForAnonDecl()) { - SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName()); + if (Error Err = importInto( + SearchName, D->getTypedefNameForAnonDecl()->getDeclName())) + return std::move(Err); IDNS = Decl::IDNS_Ordinary; } else if (Importer.getToContext().getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; @@ -2245,16 +2634,23 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } if (D->getDescribedTemplate()) { - if (auto *Template = dyn_cast<ClassTemplateDecl>(Found)) + if (auto *Template = dyn_cast<ClassTemplateDecl>(Found)) { Found = Template->getTemplatedDecl(); - else + } else { + ConflictingDecls.push_back(FoundDecl); continue; + } } if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) { if (!SearchName) { if (!IsStructuralMatch(D, FoundRecord, false)) continue; + } else { + if (!IsStructuralMatch(D, FoundRecord)) { + ConflictingDecls.push_back(FoundDecl); + continue; + } } PrevDecl = FoundRecord; @@ -2263,8 +2659,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if ((SearchName && !D->isCompleteDefinition() && !IsFriendTemplate) || (D->isCompleteDefinition() && D->isAnonymousStructOrUnion() - == FoundDef->isAnonymousStructOrUnion() && - IsStructuralMatch(D, FoundDef))) { + == FoundDef->isAnonymousStructOrUnion())) { // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. @@ -2278,10 +2673,13 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (D->isCompleteDefinition() && !Importer.isMinimalImport()) // FoundDef may not have every implicit method that D has // because implicit methods are created only if they are used. - ImportImplicitMethods(DCXX, FoundCXX); + if (Error Err = ImportImplicitMethods(DCXX, FoundCXX)) + return std::move(Err); } return FoundDef; } + if (IsFriendTemplate) + continue; } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward // declaration rather than building a new one. @@ -2297,18 +2695,18 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (FoundRecord->isCompleteDefinition() && D->isCompleteDefinition() && - !IsStructuralMatch(D, FoundRecord)) - continue; - - if (IsFriendTemplate) + !IsStructuralMatch(D, FoundRecord)) { + ConflictingDecls.push_back(FoundDecl); continue; + } AdoptDecl = FoundRecord; continue; - } else if (!SearchName) { - continue; } - } + + continue; + } else if (isa<ValueDecl>(Found)) + continue; ConflictingDecls.push_back(FoundDecl); } @@ -2317,33 +2715,40 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Name = Importer.HandleNameConflict(Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); + if (!Name) + return make_error<ImportError>(ImportError::NameConflict); } } + ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + // Create the record declaration. RecordDecl *D2 = AdoptDecl; - SourceLocation StartLoc = Importer.Import(D->getBeginLoc()); if (!D2) { CXXRecordDecl *D2CXX = nullptr; if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { if (DCXX->isLambda()) { - TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo()); + auto TInfoOrErr = import(DCXX->getLambdaTypeInfo()); + if (!TInfoOrErr) + return TInfoOrErr.takeError(); if (GetImportedOrCreateSpecialDecl( D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), - DC, TInfo, Loc, DCXX->isDependentLambda(), + DC, *TInfoOrErr, Loc, DCXX->isDependentLambda(), DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) return D2CXX; - Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl()); - if (DCXX->getLambdaContextDecl() && !CDecl) - return nullptr; - D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), CDecl); + ExpectedDecl CDeclOrErr = import(DCXX->getLambdaContextDecl()); + if (!CDeclOrErr) + return CDeclOrErr.takeError(); + D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr); } else if (DCXX->isInjectedClassName()) { // We have to be careful to do a similar dance to the one in // Sema::ActOnStartCXXMemberDeclarations CXXRecordDecl *const PrevDecl = nullptr; const bool DelayTypeCreation = true; if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), - D->getTagKind(), DC, StartLoc, Loc, + D->getTagKind(), DC, *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation)) return D2CXX; @@ -2351,7 +2756,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { D2CXX, dyn_cast<CXXRecordDecl>(DC)); } else { if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), - D->getTagKind(), DC, StartLoc, Loc, + D->getTagKind(), DC, *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), cast_or_null<CXXRecordDecl>(PrevDecl))) return D2CXX; @@ -2365,10 +2770,9 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (ClassTemplateDecl *FromDescribed = DCXX->getDescribedClassTemplate()) { - auto *ToDescribed = cast_or_null<ClassTemplateDecl>( - Importer.Import(FromDescribed)); - if (!ToDescribed) - return nullptr; + ClassTemplateDecl *ToDescribed; + if (Error Err = importInto(ToDescribed, FromDescribed)) + return std::move(Err); D2CXX->setDescribedClassTemplate(ToDescribed); if (!DCXX->isInjectedClassName() && !IsFriendTemplate) { // In a record describing a template the type should be an @@ -2398,51 +2802,58 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { TemplateSpecializationKind SK = MemberInfo->getTemplateSpecializationKind(); CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass(); - auto *ToInst = - cast_or_null<CXXRecordDecl>(Importer.Import(FromInst)); - if (FromInst && !ToInst) - return nullptr; - D2CXX->setInstantiationOfMemberClass(ToInst, SK); - D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation( - Importer.Import(MemberInfo->getPointOfInstantiation())); + + if (Expected<CXXRecordDecl *> ToInstOrErr = import(FromInst)) + D2CXX->setInstantiationOfMemberClass(*ToInstOrErr, SK); + else + return ToInstOrErr.takeError(); + + if (ExpectedSLoc POIOrErr = + import(MemberInfo->getPointOfInstantiation())) + D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation( + *POIOrErr); + else + return POIOrErr.takeError(); } + } else { if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), - D->getTagKind(), DC, StartLoc, Loc, + D->getTagKind(), DC, *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), PrevDecl)) return D2; D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); } - D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); + if (auto QualifierLocOrErr = import(D->getQualifierLoc())) + D2->setQualifierInfo(*QualifierLocOrErr); + else + return QualifierLocOrErr.takeError(); + if (D->isAnonymousStructOrUnion()) D2->setAnonymousStructOrUnion(true); } Importer.MapImported(D, D2); - if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default)) - return nullptr; + if (D->isCompleteDefinition()) + if (Error Err = ImportDefinition(D, D2, IDK_Default)) + return std::move(Err); return D2; } -Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { +ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { // Import the major distinguishing characteristics of this enumerator. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; - // Determine whether there are any other declarations with the same name and // in the same context. if (!LexicalDC->isFunctionOrMethod()) { @@ -2467,18 +2878,22 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return nullptr; + return make_error<ImportError>(ImportError::NameConflict); } } - Expr *Init = Importer.Import(D->getInitExpr()); - if (D->getInitExpr() && !Init) - return nullptr; + ExpectedType TypeOrErr = import(D->getType()); + if (!TypeOrErr) + return TypeOrErr.takeError(); + + ExpectedExpr InitOrErr = import(D->getInitExpr()); + if (!InitOrErr) + return InitOrErr.takeError(); EnumConstantDecl *ToEnumerator; if (GetImportedOrCreateDecl( ToEnumerator, D, Importer.getToContext(), cast<EnumDecl>(DC), Loc, - Name.getAsIdentifierInfo(), T, Init, D->getInitVal())) + Name.getAsIdentifierInfo(), *TypeOrErr, *InitOrErr, D->getInitVal())) return ToEnumerator; ToEnumerator->setAccess(D->getAccess()); @@ -2487,52 +2902,57 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { return ToEnumerator; } -bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, - FunctionDecl *ToFD) { +Error ASTNodeImporter::ImportTemplateInformation( + FunctionDecl *FromFD, FunctionDecl *ToFD) { switch (FromFD->getTemplatedKind()) { case FunctionDecl::TK_NonTemplate: case FunctionDecl::TK_FunctionTemplate: - return false; + return Error::success(); case FunctionDecl::TK_MemberSpecialization: { - auto *InstFD = cast_or_null<FunctionDecl>( - Importer.Import(FromFD->getInstantiatedFromMemberFunction())); - if (!InstFD) - return true; - TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind(); - SourceLocation POI = Importer.Import( - FromFD->getMemberSpecializationInfo()->getPointOfInstantiation()); - ToFD->setInstantiationOfMemberFunction(InstFD, TSK); - ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - return false; + + if (Expected<FunctionDecl *> InstFDOrErr = + import(FromFD->getInstantiatedFromMemberFunction())) + ToFD->setInstantiationOfMemberFunction(*InstFDOrErr, TSK); + else + return InstFDOrErr.takeError(); + + if (ExpectedSLoc POIOrErr = import( + FromFD->getMemberSpecializationInfo()->getPointOfInstantiation())) + ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr); + else + return POIOrErr.takeError(); + + return Error::success(); } case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateDecl* Template; - OptionalTemplateArgsTy ToTemplArgs; - std::tie(Template, ToTemplArgs) = + auto FunctionAndArgsOrErr = ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); - if (!Template || !ToTemplArgs) - return true; + if (!FunctionAndArgsOrErr) + return FunctionAndArgsOrErr.takeError(); TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy( - Importer.getToContext(), *ToTemplArgs); + Importer.getToContext(), std::get<1>(*FunctionAndArgsOrErr)); auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); TemplateArgumentListInfo ToTAInfo; const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten; if (FromTAArgsAsWritten) - if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo)) - return true; + if (Error Err = ImportTemplateArgumentListInfo( + *FromTAArgsAsWritten, ToTAInfo)) + return Err; - SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation()); + ExpectedSLoc POIOrErr = import(FTSInfo->getPointOfInstantiation()); + if (!POIOrErr) + return POIOrErr.takeError(); TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); ToFD->setFunctionTemplateSpecialization( - Template, ToTAList, /* InsertPos= */ nullptr, - TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI); - return false; + std::get<0>(*FunctionAndArgsOrErr), ToTAList, /* InsertPos= */ nullptr, + TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, *POIOrErr); + return Error::success(); } case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { @@ -2540,53 +2960,56 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, UnresolvedSet<8> TemplDecls; unsigned NumTemplates = FromInfo->getNumTemplates(); for (unsigned I = 0; I < NumTemplates; I++) { - if (auto *ToFTD = cast_or_null<FunctionTemplateDecl>( - Importer.Import(FromInfo->getTemplate(I)))) - TemplDecls.addDecl(ToFTD); + if (Expected<FunctionTemplateDecl *> ToFTDOrErr = + import(FromInfo->getTemplate(I))) + TemplDecls.addDecl(*ToFTDOrErr); else - return true; + return ToFTDOrErr.takeError(); } // Import TemplateArgumentListInfo. TemplateArgumentListInfo ToTAInfo; - if (ImportTemplateArgumentListInfo( - FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(), - llvm::makeArrayRef(FromInfo->getTemplateArgs(), - FromInfo->getNumTemplateArgs()), - ToTAInfo)) - return true; + if (Error Err = ImportTemplateArgumentListInfo( + FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(), + llvm::makeArrayRef( + FromInfo->getTemplateArgs(), FromInfo->getNumTemplateArgs()), + ToTAInfo)) + return Err; ToFD->setDependentTemplateSpecialization(Importer.getToContext(), TemplDecls, ToTAInfo); - return false; + return Error::success(); } } llvm_unreachable("All cases should be covered!"); } -FunctionDecl * +Expected<FunctionDecl *> ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { - FunctionTemplateDecl* Template; - OptionalTemplateArgsTy ToTemplArgs; - std::tie(Template, ToTemplArgs) = + auto FunctionAndArgsOrErr = ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); - if (!Template || !ToTemplArgs) - return nullptr; + if (!FunctionAndArgsOrErr) + return FunctionAndArgsOrErr.takeError(); + FunctionTemplateDecl *Template; + TemplateArgsTy ToTemplArgs; + std::tie(Template, ToTemplArgs) = *FunctionAndArgsOrErr; void *InsertPos = nullptr; - auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos); + auto *FoundSpec = Template->findSpecialization(ToTemplArgs, InsertPos); return FoundSpec; } -Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { +ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { - SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D); + SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D); auto RedeclIt = Redecls.begin(); // Import the first part of the decl chain. I.e. import all previous // declarations starting from the canonical decl. - for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) - if (!Importer.Import(*RedeclIt)) - return nullptr; + for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) { + ExpectedDecl ToRedeclOrErr = import(*RedeclIt); + if (!ToRedeclOrErr) + return ToRedeclOrErr.takeError(); + } assert(*RedeclIt == D); // Import the major distinguishing characteristics of this function. @@ -2594,8 +3017,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -2609,10 +3032,12 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // FIXME handle member function templates (TK_MemberSpecialization) similarly? if (D->getTemplatedKind() == FunctionDecl::TK_FunctionTemplateSpecialization) { - if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) { - if (D->doesThisDeclarationHaveABody() && - FoundFunction->hasBody()) - return Importer.Imported(D, FoundFunction); + auto FoundFunctionOrErr = FindFunctionTemplateSpecialization(D); + if (!FoundFunctionOrErr) + return FoundFunctionOrErr.takeError(); + if (FunctionDecl *FoundFunction = *FoundFunctionOrErr) { + if (D->doesThisDeclarationHaveABody() && FoundFunction->hasBody()) + return Importer.MapImported(D, FoundFunction); FoundByLookup = FoundFunction; } } @@ -2673,13 +3098,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return nullptr; + return make_error<ImportError>(ImportError::NameConflict); } } DeclarationNameInfo NameInfo(Name, Loc); // Import additional name location/type info. - ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) + return std::move(Err); QualType FromTy = D->getType(); bool usedDifferentExceptionSpec = false; @@ -2700,84 +3126,93 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } } - // Import the type. - QualType T = Importer.Import(FromTy); - if (T.isNull()) - return nullptr; + QualType T; + TypeSourceInfo *TInfo; + SourceLocation ToInnerLocStart, ToEndLoc; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + FromTy, D->getTypeSourceInfo(), D->getInnerLocStart(), + D->getQualifierLoc(), D->getEndLoc())) + std::tie(T, TInfo, ToInnerLocStart, ToQualifierLoc, ToEndLoc) = *Imp; + else + return Imp.takeError(); // Import the function parameters. SmallVector<ParmVarDecl *, 8> Parameters; for (auto P : D->parameters()) { - auto *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P)); - if (!ToP) - return nullptr; - - Parameters.push_back(ToP); + if (Expected<ParmVarDecl *> ToPOrErr = import(P)) + Parameters.push_back(*ToPOrErr); + else + return ToPOrErr.takeError(); } - TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - if (D->getTypeSourceInfo() && !TInfo) - return nullptr; - // Create the imported function. FunctionDecl *ToFunction = nullptr; - SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart()); if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { if (GetImportedOrCreateDecl<CXXConstructorDecl>( - ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), - InnerLocStart, NameInfo, T, TInfo, FromConstructor->isExplicit(), - D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + ToInnerLocStart, NameInfo, T, TInfo, + FromConstructor->isExplicit(), + D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) return ToFunction; - if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { - SmallVector<CXXCtorInitializer *, 4> CtorInitializers; - for (auto *I : FromConstructor->inits()) { - auto *ToI = cast_or_null<CXXCtorInitializer>(Importer.Import(I)); - if (!ToI && I) - return nullptr; - CtorInitializers.push_back(ToI); - } - auto **Memory = - new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers]; - std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory); - auto *ToCtor = cast<CXXConstructorDecl>(ToFunction); - ToCtor->setCtorInitializers(Memory); - ToCtor->setNumCtorInitializers(NumInitializers); - } } else if (isa<CXXDestructorDecl>(D)) { if (GetImportedOrCreateDecl<CXXDestructorDecl>( - ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), - InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), - D->isImplicit())) + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + D->isImplicit())) return ToFunction; } else if (CXXConversionDecl *FromConversion = dyn_cast<CXXConversionDecl>(D)) { if (GetImportedOrCreateDecl<CXXConversionDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), - InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), FromConversion->isExplicit(), D->isConstexpr(), SourceLocation())) return ToFunction; } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) { if (GetImportedOrCreateDecl<CXXMethodDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), - InnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), + ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), Method->isInlineSpecified(), D->isConstexpr(), SourceLocation())) return ToFunction; } else { if (GetImportedOrCreateDecl(ToFunction, D, Importer.getToContext(), DC, - InnerLocStart, NameInfo, T, TInfo, + ToInnerLocStart, NameInfo, T, TInfo, D->getStorageClass(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->isConstexpr())) return ToFunction; } - // Import the qualifier, if any. - ToFunction->setQualifierInfo(Importer.Import(D->getQualifierLoc())); + // Connect the redecl chain. + if (FoundByLookup) { + auto *Recent = const_cast<FunctionDecl *>( + FoundByLookup->getMostRecentDecl()); + ToFunction->setPreviousDecl(Recent); + } + + // Import Ctor initializers. + if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { + if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { + SmallVector<CXXCtorInitializer *, 4> CtorInitializers(NumInitializers); + // Import first, then allocate memory and copy if there was no error. + if (Error Err = ImportContainerChecked( + FromConstructor->inits(), CtorInitializers)) + return std::move(Err); + auto **Memory = + new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers]; + std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory); + auto *ToCtor = cast<CXXConstructorDecl>(ToFunction); + ToCtor->setCtorInitializers(Memory); + ToCtor->setNumCtorInitializers(NumInitializers); + } + } + + ToFunction->setQualifierInfo(ToQualifierLoc); ToFunction->setAccess(D->getAccess()); ToFunction->setLexicalDeclContext(LexicalDC); ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); ToFunction->setTrivial(D->isTrivial()); ToFunction->setPure(D->isPure()); - ToFunction->setRangeEnd(Importer.Import(D->getEndLoc())); + ToFunction->setRangeEnd(ToEndLoc); // Set the parameters. for (auto *Param : Parameters) { @@ -2786,12 +3221,6 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } ToFunction->setParams(Parameters); - if (FoundByLookup) { - auto *Recent = const_cast<FunctionDecl *>( - FoundByLookup->getMostRecentDecl()); - ToFunction->setPreviousDecl(Recent); - } - // We need to complete creation of FunctionProtoTypeLoc manually with setting // params it refers to. if (TInfo) { @@ -2804,30 +3233,33 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (usedDifferentExceptionSpec) { // Update FunctionProtoType::ExtProtoInfo. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; - ToFunction->setType(T); + if (ExpectedType TyOrErr = import(D->getType())) + ToFunction->setType(*TyOrErr); + else + return TyOrErr.takeError(); } // Import the describing template function, if any. - if (FromFT) - if (!Importer.Import(FromFT)) - return nullptr; + if (FromFT) { + auto ToFTOrErr = import(FromFT); + if (!ToFTOrErr) + return ToFTOrErr.takeError(); + } if (D->doesThisDeclarationHaveABody()) { if (Stmt *FromBody = D->getBody()) { - if (Stmt *ToBody = Importer.Import(FromBody)) { - ToFunction->setBody(ToBody); - } + if (ExpectedStmt ToBodyOrErr = import(FromBody)) + ToFunction->setBody(*ToBodyOrErr); + else + return ToBodyOrErr.takeError(); } } // FIXME: Other bits to merge? // If it is a template, import all related things. - if (ImportTemplateInformation(D, ToFunction)) - return nullptr; + if (Error Err = ImportTemplateInformation(D, ToFunction)) + return std::move(Err); bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend); @@ -2847,41 +3279,43 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { DC->makeDeclVisibleInContext(ToFunction); } - // Import the rest of the chain. I.e. import all subsequent declarations. - for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) - if (!Importer.Import(*RedeclIt)) - return nullptr; - if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod); + // Import the rest of the chain. I.e. import all subsequent declarations. + for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { + ExpectedDecl ToRedeclOrErr = import(*RedeclIt); + if (!ToRedeclOrErr) + return ToRedeclOrErr.takeError(); + } + return ToFunction; } -Decl *ASTNodeImporter::VisitCXXMethodDecl(CXXMethodDecl *D) { +ExpectedDecl ASTNodeImporter::VisitCXXMethodDecl(CXXMethodDecl *D) { return VisitFunctionDecl(D); } -Decl *ASTNodeImporter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { +ExpectedDecl ASTNodeImporter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { return VisitCXXMethodDecl(D); } -Decl *ASTNodeImporter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { +ExpectedDecl ASTNodeImporter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { return VisitCXXMethodDecl(D); } -Decl *ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) { +ExpectedDecl ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) { return VisitCXXMethodDecl(D); } -Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { +ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // Import the major distinguishing characteristics of a variable. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -2889,7 +3323,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (auto *FoundDecl : FoundDecls) { - if (auto *FoundField = dyn_cast<FieldDecl>(FoundDecl)) { + if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecl)) { // For anonymous fields, match up by index. if (!Name && ASTImporter::getFieldIndex(D) != @@ -2907,64 +3341,67 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // We don't have yet the initializer set. if (FoundField->hasInClassInitializer() && !FoundField->getInClassInitializer()) { - Expr *ToInitializer = Importer.Import(FromInitializer); - if (!ToInitializer) - // We can't return a nullptr here, + if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) + FoundField->setInClassInitializer(*ToInitializerOrErr); + else { + // We can't return error here, // since we already mapped D as imported. + // FIXME: warning message? + consumeError(ToInitializerOrErr.takeError()); return FoundField; - FoundField->setInClassInitializer(ToInitializer); + } } } return FoundField; } + // FIXME: Why is this case not handled with calling HandleNameConflict? Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } } - // Import the type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; - - TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - Expr *BitWidth = Importer.Import(D->getBitWidth()); - if (!BitWidth && D->getBitWidth()) - return nullptr; + QualType ToType; + TypeSourceInfo *ToTInfo; + Expr *ToBitWidth; + SourceLocation ToInnerLocStart; + Expr *ToInitializer; + if (auto Imp = importSeq( + D->getType(), D->getTypeSourceInfo(), D->getBitWidth(), + D->getInnerLocStart(), D->getInClassInitializer())) + std::tie( + ToType, ToTInfo, ToBitWidth, ToInnerLocStart, ToInitializer) = *Imp; + else + return Imp.takeError(); FieldDecl *ToField; if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), Loc, - Name.getAsIdentifierInfo(), T, TInfo, BitWidth, - D->isMutable(), D->getInClassInitStyle())) + ToInnerLocStart, Loc, Name.getAsIdentifierInfo(), + ToType, ToTInfo, ToBitWidth, D->isMutable(), + D->getInClassInitStyle())) return ToField; ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); - if (Expr *FromInitializer = D->getInClassInitializer()) { - Expr *ToInitializer = Importer.Import(FromInitializer); - if (ToInitializer) - ToField->setInClassInitializer(ToInitializer); - else - return nullptr; - } + if (ToInitializer) + ToField->setInClassInitializer(ToInitializer); ToField->setImplicit(D->isImplicit()); LexicalDC->addDeclInternal(ToField); return ToField; } -Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { +ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { // Import the major distinguishing characteristics of a variable. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -2990,39 +3427,40 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { if (!Name && I < N-1) continue; + // FIXME: Why is this case not handled with calling HandleNameConflict? Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } } // Import the type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; + auto TypeOrErr = import(D->getType()); + if (!TypeOrErr) + return TypeOrErr.takeError(); auto **NamedChain = new (Importer.getToContext()) NamedDecl*[D->getChainingSize()]; unsigned i = 0; - for (auto *PI : D->chain()) { - Decl *D = Importer.Import(PI); - if (!D) - return nullptr; - NamedChain[i++] = cast<NamedDecl>(D); - } + for (auto *PI : D->chain()) + if (Expected<NamedDecl *> ToD = import(PI)) + NamedChain[i++] = *ToD; + else + return ToD.takeError(); llvm::MutableArrayRef<NamedDecl *> CH = {NamedChain, D->getChainingSize()}; IndirectFieldDecl *ToIndirectField; if (GetImportedOrCreateDecl(ToIndirectField, D, Importer.getToContext(), DC, - Loc, Name.getAsIdentifierInfo(), T, CH)) + Loc, Name.getAsIdentifierInfo(), *TypeOrErr, CH)) // FIXME here we leak `NamedChain` which is allocated before return ToIndirectField; - for (const auto *A : D->attrs()) - ToIndirectField->addAttr(Importer.Import(A)); + for (const auto *Attr : D->attrs()) + ToIndirectField->addAttr(Importer.Import(Attr)); ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); @@ -3030,13 +3468,11 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { return ToIndirectField; } -Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { +ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { // Import the major distinguishing characteristics of a declaration. - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext() - ? DC : Importer.ImportContext(D->getLexicalDeclContext()); - if (!DC || !LexicalDC) - return nullptr; + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); // Determine whether we've already imported this decl. // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup. @@ -3061,30 +3497,42 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { // Not found. Create it. FriendDecl::FriendUnion ToFU; if (NamedDecl *FriendD = D->getFriendDecl()) { - auto *ToFriendD = cast_or_null<NamedDecl>(Importer.Import(FriendD)); - if (ToFriendD && FriendD->getFriendObjectKind() != Decl::FOK_None && + NamedDecl *ToFriendD; + if (Error Err = importInto(ToFriendD, FriendD)) + return std::move(Err); + + if (FriendD->getFriendObjectKind() != Decl::FOK_None && !(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator))) ToFriendD->setObjectOfFriendDecl(false); ToFU = ToFriendD; - } else // The friend is a type, not a decl. - ToFU = Importer.Import(D->getFriendType()); - if (!ToFU) - return nullptr; + } else { // The friend is a type, not a decl. + if (auto TSIOrErr = import(D->getFriendType())) + ToFU = *TSIOrErr; + else + return TSIOrErr.takeError(); + } SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists); auto **FromTPLists = D->getTrailingObjects<TemplateParameterList *>(); for (unsigned I = 0; I < D->NumTPLists; I++) { - TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]); - if (!List) - return nullptr; - ToTPLists[I] = List; + if (auto ListOrErr = ImportTemplateParameterList(FromTPLists[I])) + ToTPLists[I] = *ListOrErr; + else + return ListOrErr.takeError(); } + auto LocationOrErr = import(D->getLocation()); + if (!LocationOrErr) + return LocationOrErr.takeError(); + auto FriendLocOrErr = import(D->getFriendLoc()); + if (!FriendLocOrErr) + return FriendLocOrErr.takeError(); + FriendDecl *FrD; if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC, - Importer.Import(D->getLocation()), ToFU, - Importer.Import(D->getFriendLoc()), ToTPLists)) + *LocationOrErr, ToFU, + *FriendLocOrErr, ToTPLists)) return FrD; FrD->setAccess(D->getAccess()); @@ -3093,14 +3541,14 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { return FrD; } -Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { +ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Import the major distinguishing characteristics of an ivar. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -3108,7 +3556,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (auto *FoundDecl : FoundDecls) { - if (auto *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) { + if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { Importer.MapImported(D, FoundIvar); @@ -3119,26 +3567,27 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { << Name << D->getType() << FoundIvar->getType(); Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) << FoundIvar->getType(); - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } } - // Import the type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; - - TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - Expr *BitWidth = Importer.Import(D->getBitWidth()); - if (!BitWidth && D->getBitWidth()) - return nullptr; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + Expr *ToBitWidth; + SourceLocation ToInnerLocStart; + if (auto Imp = importSeq( + D->getType(), D->getTypeSourceInfo(), D->getBitWidth(), D->getInnerLocStart())) + std::tie(ToType, ToTypeSourceInfo, ToBitWidth, ToInnerLocStart) = *Imp; + else + return Imp.takeError(); ObjCIvarDecl *ToIvar; if (GetImportedOrCreateDecl( ToIvar, D, Importer.getToContext(), cast<ObjCContainerDecl>(DC), - Importer.Import(D->getInnerLocStart()), Loc, - Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), BitWidth, - D->getSynthesize())) + ToInnerLocStart, Loc, Name.getAsIdentifierInfo(), + ToType, ToTypeSourceInfo, + D->getAccessControl(),ToBitWidth, D->getSynthesize())) return ToIvar; ToIvar->setLexicalDeclContext(LexicalDC); @@ -3146,15 +3595,17 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { return ToIvar; } -Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { +ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) { SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D); auto RedeclIt = Redecls.begin(); // Import the first part of the decl chain. I.e. import all previous // declarations starting from the canonical decl. - for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) - if (!Importer.Import(*RedeclIt)) - return nullptr; + for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) { + ExpectedDecl RedeclOrErr = import(*RedeclIt); + if (!RedeclOrErr) + return RedeclOrErr.takeError(); + } assert(*RedeclIt == D); // Import the major distinguishing characteristics of a variable. @@ -3162,8 +3613,8 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -3213,11 +3664,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { if (isa<IncompleteArrayType>(FoundArray) && isa<ConstantArrayType>(TArray)) { // Import the type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; + if (auto TyOrErr = import(D->getType())) + FoundVar->setType(*TyOrErr); + else + return TyOrErr.takeError(); - FoundVar->setType(T); FoundByLookup = FoundVar; break; } else if (isa<IncompleteArrayType>(TArray) && @@ -3242,25 +3693,31 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return nullptr; + return make_error<ImportError>(ImportError::NameConflict); } } - // Import the type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToInnerLocStart; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getType(), D->getTypeSourceInfo(), D->getInnerLocStart(), + D->getQualifierLoc())) + std::tie(ToType, ToTypeSourceInfo, ToInnerLocStart, ToQualifierLoc) = *Imp; + else + return Imp.takeError(); // Create the imported variable. - TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); VarDecl *ToVar; if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), Loc, - Name.getAsIdentifierInfo(), T, TInfo, + ToInnerLocStart, Loc, + Name.getAsIdentifierInfo(), + ToType, ToTypeSourceInfo, D->getStorageClass())) return ToVar; - ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); + ToVar->setQualifierInfo(ToQualifierLoc); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); @@ -3269,8 +3726,8 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { ToVar->setPreviousDecl(Recent); } - if (ImportInitializer(D, ToVar)) - return nullptr; + if (Error Err = ImportInitializer(D, ToVar)) + return std::move(Err); if (D->isConstexpr()) ToVar->setConstexpr(true); @@ -3281,65 +3738,60 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { LexicalDC->addDeclInternal(ToVar); // Import the rest of the chain. I.e. import all subsequent declarations. - for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) - if (!Importer.Import(*RedeclIt)) - return nullptr; + for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { + ExpectedDecl RedeclOrErr = import(*RedeclIt); + if (!RedeclOrErr) + return RedeclOrErr.takeError(); + } return ToVar; } -Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { +ExpectedDecl ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { // Parameters are created in the translation unit's context, then moved // into the function declaration's context afterward. DeclContext *DC = Importer.getToContext().getTranslationUnitDecl(); - // Import the name of this declaration. - DeclarationName Name = Importer.Import(D->getDeclName()); - if (D->getDeclName() && !Name) - return nullptr; - - // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); - - // Import the parameter's type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; + DeclarationName ToDeclName; + SourceLocation ToLocation; + QualType ToType; + if (auto Imp = importSeq(D->getDeclName(), D->getLocation(), D->getType())) + std::tie(ToDeclName, ToLocation, ToType) = *Imp; + else + return Imp.takeError(); // Create the imported parameter. ImplicitParamDecl *ToParm = nullptr; - if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), T, - D->getParameterKind())) + if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, + ToLocation, ToDeclName.getAsIdentifierInfo(), + ToType, D->getParameterKind())) return ToParm; return ToParm; } -Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { +ExpectedDecl ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { // Parameters are created in the translation unit's context, then moved // into the function declaration's context afterward. DeclContext *DC = Importer.getToContext().getTranslationUnitDecl(); - // Import the name of this declaration. - DeclarationName Name = Importer.Import(D->getDeclName()); - if (D->getDeclName() && !Name) - return nullptr; - - // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); - - // Import the parameter's type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; + DeclarationName ToDeclName; + SourceLocation ToLocation, ToInnerLocStart; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + if (auto Imp = importSeq( + D->getDeclName(), D->getLocation(), D->getType(), D->getInnerLocStart(), + D->getTypeSourceInfo())) + std::tie( + ToDeclName, ToLocation, ToType, ToInnerLocStart, + ToTypeSourceInfo) = *Imp; + else + return Imp.takeError(); - // Create the imported parameter. - TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); ParmVarDecl *ToParm; if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), Loc, - Name.getAsIdentifierInfo(), T, TInfo, - D->getStorageClass(), + ToInnerLocStart, ToLocation, + ToDeclName.getAsIdentifierInfo(), ToType, + ToTypeSourceInfo, D->getStorageClass(), /*DefaultArg*/ nullptr)) return ToParm; @@ -3347,21 +3799,19 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); ToParm->setKNRPromoted(D->isKNRPromoted()); - Expr *ToDefArg = nullptr; - Expr *FromDefArg = nullptr; if (D->hasUninstantiatedDefaultArg()) { - FromDefArg = D->getUninstantiatedDefaultArg(); - ToDefArg = Importer.Import(FromDefArg); - ToParm->setUninstantiatedDefaultArg(ToDefArg); + if (auto ToDefArgOrErr = import(D->getUninstantiatedDefaultArg())) + ToParm->setUninstantiatedDefaultArg(*ToDefArgOrErr); + else + return ToDefArgOrErr.takeError(); } else if (D->hasUnparsedDefaultArg()) { ToParm->setUnparsedDefaultArg(); } else if (D->hasDefaultArg()) { - FromDefArg = D->getDefaultArg(); - ToDefArg = Importer.Import(FromDefArg); - ToParm->setDefaultArg(ToDefArg); + if (auto ToDefArgOrErr = import(D->getDefaultArg())) + ToParm->setDefaultArg(*ToDefArgOrErr); + else + return ToDefArgOrErr.takeError(); } - if (FromDefArg && !ToDefArg) - return nullptr; if (D->isObjCMethodParameter()) { ToParm->setObjCMethodScopeInfo(D->getFunctionScopeIndex()); @@ -3374,14 +3824,14 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { return ToParm; } -Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { +ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Import the major distinguishing characteristics of a method. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -3401,7 +3851,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } // Check the number of parameters. @@ -3412,7 +3863,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } // Check parameter types. @@ -3427,7 +3879,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { << (*P)->getType() << (*FoundP)->getType(); Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) << (*FoundP)->getType(); - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } } @@ -3439,7 +3892,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } // FIXME: Any other bits we need to merge? @@ -3447,18 +3901,20 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { } } - // Import the result type. - QualType ResultTy = Importer.Import(D->getReturnType()); - if (ResultTy.isNull()) - return nullptr; - - TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo()); + SourceLocation ToEndLoc; + QualType ToReturnType; + TypeSourceInfo *ToReturnTypeSourceInfo; + if (auto Imp = importSeq( + D->getEndLoc(), D->getReturnType(), D->getReturnTypeSourceInfo())) + std::tie(ToEndLoc, ToReturnType, ToReturnTypeSourceInfo) = *Imp; + else + return Imp.takeError(); ObjCMethodDecl *ToMethod; if (GetImportedOrCreateDecl( ToMethod, D, Importer.getToContext(), Loc, - Importer.Import(D->getEndLoc()), Name.getObjCSelector(), ResultTy, - ReturnTInfo, DC, D->isInstanceMethod(), D->isVariadic(), + ToEndLoc, Name.getObjCSelector(), ToReturnType, + ToReturnTypeSourceInfo, DC, D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), D->getImplementationControl(), D->hasRelatedResultType())) return ToMethod; @@ -3469,11 +3925,10 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Import the parameters SmallVector<ParmVarDecl *, 5> ToParams; for (auto *FromP : D->parameters()) { - auto *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP)); - if (!ToP) - return nullptr; - - ToParams.push_back(ToP); + if (Expected<ParmVarDecl *> ToPOrErr = import(FromP)) + ToParams.push_back(*ToPOrErr); + else + return ToPOrErr.takeError(); } // Set the parameters. @@ -3482,82 +3937,99 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { ToMethod->addDeclInternal(ToParam); } - SmallVector<SourceLocation, 12> SelLocs; - D->getSelectorLocs(SelLocs); - for (auto &Loc : SelLocs) - Loc = Importer.Import(Loc); + SmallVector<SourceLocation, 12> FromSelLocs; + D->getSelectorLocs(FromSelLocs); + SmallVector<SourceLocation, 12> ToSelLocs(FromSelLocs.size()); + if (Error Err = ImportContainerChecked(FromSelLocs, ToSelLocs)) + return std::move(Err); - ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs); + ToMethod->setMethodParams(Importer.getToContext(), ToParams, ToSelLocs); ToMethod->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToMethod); return ToMethod; } -Decl *ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { +ExpectedDecl ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { // Import the major distinguishing characteristics of a category. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; - TypeSourceInfo *BoundInfo = Importer.Import(D->getTypeSourceInfo()); - if (!BoundInfo) - return nullptr; + SourceLocation ToVarianceLoc, ToLocation, ToColonLoc; + TypeSourceInfo *ToTypeSourceInfo; + if (auto Imp = importSeq( + D->getVarianceLoc(), D->getLocation(), D->getColonLoc(), + D->getTypeSourceInfo())) + std::tie(ToVarianceLoc, ToLocation, ToColonLoc, ToTypeSourceInfo) = *Imp; + else + return Imp.takeError(); ObjCTypeParamDecl *Result; if (GetImportedOrCreateDecl( Result, D, Importer.getToContext(), DC, D->getVariance(), - Importer.Import(D->getVarianceLoc()), D->getIndex(), - Importer.Import(D->getLocation()), Name.getAsIdentifierInfo(), - Importer.Import(D->getColonLoc()), BoundInfo)) + ToVarianceLoc, D->getIndex(), + ToLocation, Name.getAsIdentifierInfo(), + ToColonLoc, ToTypeSourceInfo)) return Result; Result->setLexicalDeclContext(LexicalDC); return Result; } -Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { +ExpectedDecl ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { // Import the major distinguishing characteristics of a category. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; - auto *ToInterface = - cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface())); - if (!ToInterface) - return nullptr; + ObjCInterfaceDecl *ToInterface; + if (Error Err = importInto(ToInterface, D->getClassInterface())) + return std::move(Err); // Determine if we've already encountered this category. ObjCCategoryDecl *MergeWithCategory = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo()); ObjCCategoryDecl *ToCategory = MergeWithCategory; if (!ToCategory) { + SourceLocation ToAtStartLoc, ToCategoryNameLoc; + SourceLocation ToIvarLBraceLoc, ToIvarRBraceLoc; + if (auto Imp = importSeq( + D->getAtStartLoc(), D->getCategoryNameLoc(), + D->getIvarLBraceLoc(), D->getIvarRBraceLoc())) + std::tie( + ToAtStartLoc, ToCategoryNameLoc, + ToIvarLBraceLoc, ToIvarRBraceLoc) = *Imp; + else + return Imp.takeError(); if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), Loc, - Importer.Import(D->getCategoryNameLoc()), + ToAtStartLoc, Loc, + ToCategoryNameLoc, Name.getAsIdentifierInfo(), ToInterface, /*TypeParamList=*/nullptr, - Importer.Import(D->getIvarLBraceLoc()), - Importer.Import(D->getIvarRBraceLoc()))) + ToIvarLBraceLoc, + ToIvarRBraceLoc)) return ToCategory; ToCategory->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToCategory); - // Import the type parameter list after calling Imported, to avoid + // Import the type parameter list after MapImported, to avoid // loops when bringing in their DeclContext. - ToCategory->setTypeParamList(ImportObjCTypeParamList( - D->getTypeParamList())); + if (auto PListOrErr = ImportObjCTypeParamList(D->getTypeParamList())) + ToCategory->setTypeParamList(*PListOrErr); + else + return PListOrErr.takeError(); // Import protocols SmallVector<ObjCProtocolDecl *, 4> Protocols; @@ -3568,45 +4040,48 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { FromProtoEnd = D->protocol_end(); FromProto != FromProtoEnd; ++FromProto, ++FromProtoLoc) { - auto *ToProto = - cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); - if (!ToProto) - return nullptr; - Protocols.push_back(ToProto); - ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto)) + Protocols.push_back(*ToProtoOrErr); + else + return ToProtoOrErr.takeError(); + + if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc)) + ProtocolLocs.push_back(*ToProtoLocOrErr); + else + return ToProtoLocOrErr.takeError(); } // FIXME: If we're merging, make sure that the protocol list is the same. ToCategory->setProtocolList(Protocols.data(), Protocols.size(), ProtocolLocs.data(), Importer.getToContext()); + } else { Importer.MapImported(D, ToCategory); } // Import all of the members of this category. - ImportDeclContext(D); + if (Error Err = ImportDeclContext(D)) + return std::move(Err); // If we have an implementation, import it as well. if (D->getImplementation()) { - auto *Impl = - cast_or_null<ObjCCategoryImplDecl>( - Importer.Import(D->getImplementation())); - if (!Impl) - return nullptr; - - ToCategory->setImplementation(Impl); + if (Expected<ObjCCategoryImplDecl *> ToImplOrErr = + import(D->getImplementation())) + ToCategory->setImplementation(*ToImplOrErr); + else + return ToImplOrErr.takeError(); } return ToCategory; } -bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From, - ObjCProtocolDecl *To, - ImportDefinitionKind Kind) { +Error ASTNodeImporter::ImportDefinition( + ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind) { if (To->getDefinition()) { if (shouldForceImportDeclContext(Kind)) - ImportDeclContext(From); - return false; + if (Error Err = ImportDeclContext(From)) + return Err; + return Error::success(); } // Start the protocol definition @@ -3615,17 +4090,22 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From, // Import protocols SmallVector<ObjCProtocolDecl *, 4> Protocols; SmallVector<SourceLocation, 4> ProtocolLocs; - ObjCProtocolDecl::protocol_loc_iterator - FromProtoLoc = From->protocol_loc_begin(); + ObjCProtocolDecl::protocol_loc_iterator FromProtoLoc = + From->protocol_loc_begin(); for (ObjCProtocolDecl::protocol_iterator FromProto = From->protocol_begin(), FromProtoEnd = From->protocol_end(); FromProto != FromProtoEnd; ++FromProto, ++FromProtoLoc) { - auto *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); - if (!ToProto) - return true; - Protocols.push_back(ToProto); - ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto)) + Protocols.push_back(*ToProtoOrErr); + else + return ToProtoOrErr.takeError(); + + if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc)) + ProtocolLocs.push_back(*ToProtoLocOrErr); + else + return ToProtoLocOrErr.takeError(); + } // FIXME: If we're merging, make sure that the protocol list is the same. @@ -3634,22 +4114,22 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From, if (shouldForceImportDeclContext(Kind)) { // Import all of the members of this protocol. - ImportDeclContext(From, /*ForceImport=*/true); + if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) + return Err; } - return false; + return Error::success(); } -Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { +ExpectedDecl ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { // If this protocol has a definition in the translation unit we're coming // from, but this particular declaration is not that definition, import the // definition and map to that. ObjCProtocolDecl *Definition = D->getDefinition(); if (Definition && Definition != D) { - Decl *ImportedDef = Importer.Import(Definition); - if (!ImportedDef) - return nullptr; - - return Importer.MapImported(D, ImportedDef); + if (ExpectedDecl ImportedDefOrErr = import(Definition)) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); } // Import the major distinguishing characteristics of a protocol. @@ -3657,8 +4137,8 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -3675,9 +4155,13 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { ObjCProtocolDecl *ToProto = MergeWithProtocol; if (!ToProto) { + auto ToAtBeginLocOrErr = import(D->getAtStartLoc()); + if (!ToAtBeginLocOrErr) + return ToAtBeginLocOrErr.takeError(); + if (GetImportedOrCreateDecl(ToProto, D, Importer.getToContext(), DC, Name.getAsIdentifierInfo(), Loc, - Importer.Import(D->getAtStartLoc()), + *ToAtBeginLocOrErr, /*PrevDecl=*/nullptr)) return ToProto; ToProto->setLexicalDeclContext(LexicalDC); @@ -3686,29 +4170,39 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { Importer.MapImported(D, ToProto); - if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto)) - return nullptr; + if (D->isThisDeclarationADefinition()) + if (Error Err = ImportDefinition(D, ToProto)) + return std::move(Err); return ToProto; } -Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); +ExpectedDecl ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); - SourceLocation ExternLoc = Importer.Import(D->getExternLoc()); - SourceLocation LangLoc = Importer.Import(D->getLocation()); + ExpectedSLoc ExternLocOrErr = import(D->getExternLoc()); + if (!ExternLocOrErr) + return ExternLocOrErr.takeError(); + + ExpectedSLoc LangLocOrErr = import(D->getLocation()); + if (!LangLocOrErr) + return LangLocOrErr.takeError(); bool HasBraces = D->hasBraces(); LinkageSpecDecl *ToLinkageSpec; if (GetImportedOrCreateDecl(ToLinkageSpec, D, Importer.getToContext(), DC, - ExternLoc, LangLoc, D->getLanguage(), HasBraces)) + *ExternLocOrErr, *LangLocOrErr, + D->getLanguage(), HasBraces)) return ToLinkageSpec; if (HasBraces) { - SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc()); - ToLinkageSpec->setRBraceLoc(RBraceLoc); + ExpectedSLoc RBraceLocOrErr = import(D->getRBraceLoc()); + if (!RBraceLocOrErr) + return RBraceLocOrErr.takeError(); + ToLinkageSpec->setRBraceLoc(*RBraceLocOrErr); } ToLinkageSpec->setLexicalDeclContext(LexicalDC); @@ -3717,24 +4211,31 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { return ToLinkageSpec; } -Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { +ExpectedDecl ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; - DeclarationNameInfo NameInfo(Name, - Importer.Import(D->getNameInfo().getLoc())); - ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + SourceLocation ToLoc, ToUsingLoc; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getNameInfo().getLoc(), D->getUsingLoc(), D->getQualifierLoc())) + std::tie(ToLoc, ToUsingLoc, ToQualifierLoc) = *Imp; + else + return Imp.takeError(); + + DeclarationNameInfo NameInfo(Name, ToLoc); + if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) + return std::move(Err); UsingDecl *ToUsing; if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, - Importer.Import(D->getUsingLoc()), - Importer.Import(D->getQualifierLoc()), NameInfo, + ToUsingLoc, ToQualifierLoc, NameInfo, D->hasTypename())) return ToUsing; @@ -3743,48 +4244,45 @@ Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { if (NamedDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { - if (auto *ToPattern = - dyn_cast_or_null<NamedDecl>(Importer.Import(FromPattern))) - Importer.getToContext().setInstantiatedFromUsingDecl(ToUsing, ToPattern); + if (Expected<NamedDecl *> ToPatternOrErr = import(FromPattern)) + Importer.getToContext().setInstantiatedFromUsingDecl( + ToUsing, *ToPatternOrErr); else - return nullptr; + return ToPatternOrErr.takeError(); } - for (auto *FromShadow : D->shadows()) { - if (auto *ToShadow = - dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromShadow))) - ToUsing->addShadowDecl(ToShadow); + for (UsingShadowDecl *FromShadow : D->shadows()) { + if (Expected<UsingShadowDecl *> ToShadowOrErr = import(FromShadow)) + ToUsing->addShadowDecl(*ToShadowOrErr); else - // FIXME: We return a nullptr here but the definition is already created + // FIXME: We return error here but the definition is already created // and available with lookups. How to fix this?.. - return nullptr; + return ToShadowOrErr.takeError(); } return ToUsing; } -Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { +ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; - auto *ToUsing = dyn_cast_or_null<UsingDecl>( - Importer.Import(D->getUsingDecl())); - if (!ToUsing) - return nullptr; + Expected<UsingDecl *> ToUsingOrErr = import(D->getUsingDecl()); + if (!ToUsingOrErr) + return ToUsingOrErr.takeError(); - auto *ToTarget = dyn_cast_or_null<NamedDecl>( - Importer.Import(D->getTargetDecl())); - if (!ToTarget) - return nullptr; + Expected<NamedDecl *> ToTargetOrErr = import(D->getTargetDecl()); + if (!ToTargetOrErr) + return ToTargetOrErr.takeError(); UsingShadowDecl *ToShadow; if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, - ToUsing, ToTarget)) + *ToUsingOrErr, *ToTargetOrErr)) return ToShadow; ToShadow->setLexicalDeclContext(LexicalDC); @@ -3792,14 +4290,13 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { if (UsingShadowDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { - if (auto *ToPattern = - dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromPattern))) - Importer.getToContext().setInstantiatedFromUsingShadowDecl(ToShadow, - ToPattern); + if (Expected<UsingShadowDecl *> ToPatternOrErr = import(FromPattern)) + Importer.getToContext().setInstantiatedFromUsingShadowDecl( + ToShadow, *ToPatternOrErr); else - // FIXME: We return a nullptr here but the definition is already created + // FIXME: We return error here but the definition is already created // and available with lookups. How to fix this?.. - return nullptr; + return ToPatternOrErr.takeError(); } LexicalDC->addDeclInternal(ToShadow); @@ -3807,32 +4304,40 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { return ToShadow; } -Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { +ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; - DeclContext *ToComAncestor = Importer.ImportContext(D->getCommonAncestor()); - if (!ToComAncestor) - return nullptr; - - auto *ToNominated = cast_or_null<NamespaceDecl>( - Importer.Import(D->getNominatedNamespace())); - if (!ToNominated) - return nullptr; + auto ToComAncestorOrErr = Importer.ImportContext(D->getCommonAncestor()); + if (!ToComAncestorOrErr) + return ToComAncestorOrErr.takeError(); + + NamespaceDecl *ToNominatedNamespace; + SourceLocation ToUsingLoc, ToNamespaceKeyLocation, ToIdentLocation; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getNominatedNamespace(), D->getUsingLoc(), + D->getNamespaceKeyLocation(), D->getQualifierLoc(), + D->getIdentLocation())) + std::tie( + ToNominatedNamespace, ToUsingLoc, ToNamespaceKeyLocation, + ToQualifierLoc, ToIdentLocation) = *Imp; + else + return Imp.takeError(); UsingDirectiveDecl *ToUsingDir; if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC, - Importer.Import(D->getUsingLoc()), - Importer.Import(D->getNamespaceKeyLocation()), - Importer.Import(D->getQualifierLoc()), - Importer.Import(D->getIdentLocation()), - ToNominated, ToComAncestor)) + ToUsingLoc, + ToNamespaceKeyLocation, + ToQualifierLoc, + ToIdentLocation, + ToNominatedNamespace, *ToComAncestorOrErr)) return ToUsingDir; ToUsingDir->setLexicalDeclContext(LexicalDC); @@ -3841,25 +4346,34 @@ Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { return ToUsingDir; } -Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl( +ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingValueDecl( UnresolvedUsingValueDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; - DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc())); - ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + SourceLocation ToLoc, ToUsingLoc, ToEllipsisLoc; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getNameInfo().getLoc(), D->getUsingLoc(), D->getQualifierLoc(), + D->getEllipsisLoc())) + std::tie(ToLoc, ToUsingLoc, ToQualifierLoc, ToEllipsisLoc) = *Imp; + else + return Imp.takeError(); + + DeclarationNameInfo NameInfo(Name, ToLoc); + if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) + return std::move(Err); UnresolvedUsingValueDecl *ToUsingValue; if (GetImportedOrCreateDecl(ToUsingValue, D, Importer.getToContext(), DC, - Importer.Import(D->getUsingLoc()), - Importer.Import(D->getQualifierLoc()), NameInfo, - Importer.Import(D->getEllipsisLoc()))) + ToUsingLoc, ToQualifierLoc, NameInfo, + ToEllipsisLoc)) return ToUsingValue; ToUsingValue->setAccess(D->getAccess()); @@ -3869,23 +4383,30 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl( return ToUsingValue; } -Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( +ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; + SourceLocation ToUsingLoc, ToTypenameLoc, ToEllipsisLoc; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getUsingLoc(), D->getTypenameLoc(), D->getQualifierLoc(), + D->getEllipsisLoc())) + std::tie(ToUsingLoc, ToTypenameLoc, ToQualifierLoc, ToEllipsisLoc) = *Imp; + else + return Imp.takeError(); + UnresolvedUsingTypenameDecl *ToUsing; if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, - Importer.Import(D->getUsingLoc()), - Importer.Import(D->getTypenameLoc()), - Importer.Import(D->getQualifierLoc()), Loc, Name, - Importer.Import(D->getEllipsisLoc()))) + ToUsingLoc, ToTypenameLoc, + ToQualifierLoc, Loc, Name, ToEllipsisLoc)) return ToUsing; ToUsing->setAccess(D->getAccess()); @@ -3895,16 +4416,17 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( return ToUsing; } -bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, - ObjCInterfaceDecl *To, - ImportDefinitionKind Kind) { + +Error ASTNodeImporter::ImportDefinition( + ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { if (To->getDefinition()) { // Check consistency of superclass. ObjCInterfaceDecl *FromSuper = From->getSuperClass(); if (FromSuper) { - FromSuper = cast_or_null<ObjCInterfaceDecl>(Importer.Import(FromSuper)); - if (!FromSuper) - return true; + if (auto FromSuperOrErr = import(FromSuper)) + FromSuper = *FromSuperOrErr; + else + return FromSuperOrErr.takeError(); } ObjCInterfaceDecl *ToSuper = To->getSuperClass(); @@ -3929,8 +4451,9 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, } if (shouldForceImportDeclContext(Kind)) - ImportDeclContext(From); - return false; + if (Error Err = ImportDeclContext(From)) + return Err; + return Error::success(); } // Start the definition. @@ -3938,28 +4461,32 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, // If this class has a superclass, import it. if (From->getSuperClass()) { - TypeSourceInfo *SuperTInfo = Importer.Import(From->getSuperClassTInfo()); - if (!SuperTInfo) - return true; - - To->setSuperClass(SuperTInfo); + if (auto SuperTInfoOrErr = import(From->getSuperClassTInfo())) + To->setSuperClass(*SuperTInfoOrErr); + else + return SuperTInfoOrErr.takeError(); } // Import protocols SmallVector<ObjCProtocolDecl *, 4> Protocols; SmallVector<SourceLocation, 4> ProtocolLocs; - ObjCInterfaceDecl::protocol_loc_iterator - FromProtoLoc = From->protocol_loc_begin(); + ObjCInterfaceDecl::protocol_loc_iterator FromProtoLoc = + From->protocol_loc_begin(); for (ObjCInterfaceDecl::protocol_iterator FromProto = From->protocol_begin(), FromProtoEnd = From->protocol_end(); FromProto != FromProtoEnd; ++FromProto, ++FromProtoLoc) { - auto *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); - if (!ToProto) - return true; - Protocols.push_back(ToProto); - ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto)) + Protocols.push_back(*ToProtoOrErr); + else + return ToProtoOrErr.takeError(); + + if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc)) + ProtocolLocs.push_back(*ToProtoLocOrErr); + else + return ToProtoLocOrErr.takeError(); + } // FIXME: If we're merging, make sure that the protocol list is the same. @@ -3968,58 +4495,66 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, // Import categories. When the categories themselves are imported, they'll // hook themselves into this interface. - for (auto *Cat : From->known_categories()) - Importer.Import(Cat); + for (auto *Cat : From->known_categories()) { + auto ToCatOrErr = import(Cat); + if (!ToCatOrErr) + return ToCatOrErr.takeError(); + } // If we have an @implementation, import it as well. if (From->getImplementation()) { - auto *Impl = cast_or_null<ObjCImplementationDecl>( - Importer.Import(From->getImplementation())); - if (!Impl) - return true; - - To->setImplementation(Impl); + if (Expected<ObjCImplementationDecl *> ToImplOrErr = + import(From->getImplementation())) + To->setImplementation(*ToImplOrErr); + else + return ToImplOrErr.takeError(); } if (shouldForceImportDeclContext(Kind)) { // Import all of the members of this class. - ImportDeclContext(From, /*ForceImport=*/true); + if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) + return Err; } - return false; + return Error::success(); } -ObjCTypeParamList * +Expected<ObjCTypeParamList *> ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) { if (!list) return nullptr; SmallVector<ObjCTypeParamDecl *, 4> toTypeParams; - for (auto fromTypeParam : *list) { - auto *toTypeParam = cast_or_null<ObjCTypeParamDecl>( - Importer.Import(fromTypeParam)); - if (!toTypeParam) - return nullptr; - - toTypeParams.push_back(toTypeParam); + for (auto *fromTypeParam : *list) { + if (auto toTypeParamOrErr = import(fromTypeParam)) + toTypeParams.push_back(*toTypeParamOrErr); + else + return toTypeParamOrErr.takeError(); } + auto LAngleLocOrErr = import(list->getLAngleLoc()); + if (!LAngleLocOrErr) + return LAngleLocOrErr.takeError(); + + auto RAngleLocOrErr = import(list->getRAngleLoc()); + if (!RAngleLocOrErr) + return RAngleLocOrErr.takeError(); + return ObjCTypeParamList::create(Importer.getToContext(), - Importer.Import(list->getLAngleLoc()), + *LAngleLocOrErr, toTypeParams, - Importer.Import(list->getRAngleLoc())); + *RAngleLocOrErr); } -Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { +ExpectedDecl ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // If this class has a definition in the translation unit we're coming from, // but this particular declaration is not that definition, import the // definition and map to that. ObjCInterfaceDecl *Definition = D->getDefinition(); if (Definition && Definition != D) { - Decl *ImportedDef = Importer.Import(Definition); - if (!ImportedDef) - return nullptr; - - return Importer.MapImported(D, ImportedDef); + if (ExpectedDecl ImportedDefOrErr = import(Definition)) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); } // Import the major distinguishing characteristics of an @interface. @@ -4027,8 +4562,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -4047,9 +4582,13 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Create an interface declaration, if one does not already exist. ObjCInterfaceDecl *ToIface = MergeWithIface; if (!ToIface) { + ExpectedSLoc AtBeginLocOrErr = import(D->getAtStartLoc()); + if (!AtBeginLocOrErr) + return AtBeginLocOrErr.takeError(); + if (GetImportedOrCreateDecl( ToIface, D, Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), + *AtBeginLocOrErr, Name.getAsIdentifierInfo(), /*TypeParamList=*/nullptr, /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl())) return ToIface; @@ -4057,91 +4596,99 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { LexicalDC->addDeclInternal(ToIface); } Importer.MapImported(D, ToIface); - // Import the type parameter list after calling Imported, to avoid + // Import the type parameter list after MapImported, to avoid // loops when bringing in their DeclContext. - ToIface->setTypeParamList(ImportObjCTypeParamList( - D->getTypeParamListAsWritten())); + if (auto ToPListOrErr = + ImportObjCTypeParamList(D->getTypeParamListAsWritten())) + ToIface->setTypeParamList(*ToPListOrErr); + else + return ToPListOrErr.takeError(); - if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface)) - return nullptr; + if (D->isThisDeclarationADefinition()) + if (Error Err = ImportDefinition(D, ToIface)) + return std::move(Err); return ToIface; } -Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { - auto *Category = cast_or_null<ObjCCategoryDecl>( - Importer.Import(D->getCategoryDecl())); - if (!Category) - return nullptr; +ExpectedDecl +ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { + ObjCCategoryDecl *Category; + if (Error Err = importInto(Category, D->getCategoryDecl())) + return std::move(Err); ObjCCategoryImplDecl *ToImpl = Category->getImplementation(); if (!ToImpl) { - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - if (!DC) - return nullptr; + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); + + SourceLocation ToLocation, ToAtStartLoc, ToCategoryNameLoc; + if (auto Imp = importSeq( + D->getLocation(), D->getAtStartLoc(), D->getCategoryNameLoc())) + std::tie(ToLocation, ToAtStartLoc, ToCategoryNameLoc) = *Imp; + else + return Imp.takeError(); - SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc()); if (GetImportedOrCreateDecl( ToImpl, D, Importer.getToContext(), DC, Importer.Import(D->getIdentifier()), Category->getClassInterface(), - Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc()), CategoryNameLoc)) + ToLocation, ToAtStartLoc, ToCategoryNameLoc)) return ToImpl; - DeclContext *LexicalDC = DC; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return nullptr; - - ToImpl->setLexicalDeclContext(LexicalDC); - } - + ToImpl->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToImpl); Category->setImplementation(ToImpl); } Importer.MapImported(D, ToImpl); - ImportDeclContext(D); + if (Error Err = ImportDeclContext(D)) + return std::move(Err); + return ToImpl; } -Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { +ExpectedDecl +ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { // Find the corresponding interface. - auto *Iface = cast_or_null<ObjCInterfaceDecl>( - Importer.Import(D->getClassInterface())); - if (!Iface) - return nullptr; + ObjCInterfaceDecl *Iface; + if (Error Err = importInto(Iface, D->getClassInterface())) + return std::move(Err); // Import the superclass, if any. - ObjCInterfaceDecl *Super = nullptr; - if (D->getSuperClass()) { - Super = cast_or_null<ObjCInterfaceDecl>( - Importer.Import(D->getSuperClass())); - if (!Super) - return nullptr; - } + ObjCInterfaceDecl *Super; + if (Error Err = importInto(Super, D->getSuperClass())) + return std::move(Err); ObjCImplementationDecl *Impl = Iface->getImplementation(); if (!Impl) { // We haven't imported an implementation yet. Create a new @implementation // now. + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); + + SourceLocation ToLocation, ToAtStartLoc, ToSuperClassLoc; + SourceLocation ToIvarLBraceLoc, ToIvarRBraceLoc; + if (auto Imp = importSeq( + D->getLocation(), D->getAtStartLoc(), D->getSuperClassLoc(), + D->getIvarLBraceLoc(), D->getIvarRBraceLoc())) + std::tie( + ToLocation, ToAtStartLoc, ToSuperClassLoc, + ToIvarLBraceLoc, ToIvarRBraceLoc) = *Imp; + else + return Imp.takeError(); + if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(), - Importer.ImportContext(D->getDeclContext()), - Iface, Super, Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc()), - Importer.Import(D->getSuperClassLoc()), - Importer.Import(D->getIvarLBraceLoc()), - Importer.Import(D->getIvarRBraceLoc()))) + DC, Iface, Super, + ToLocation, + ToAtStartLoc, + ToSuperClassLoc, + ToIvarLBraceLoc, + ToIvarRBraceLoc)) return Impl; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - DeclContext *LexicalDC - = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return nullptr; - Impl->setLexicalDeclContext(LexicalDC); - } + Impl->setLexicalDeclContext(LexicalDC); // Associate the implementation with the class it implements. Iface->setImplementation(Impl); @@ -4174,24 +4721,26 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { else Importer.FromDiag(D->getLocation(), diag::note_odr_objc_missing_superclass); - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } } // Import all of the members of this @implementation. - ImportDeclContext(D); + if (Error Err = ImportDeclContext(D)) + return std::move(Err); return Impl; } -Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { +ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // Import the major distinguishing characteristics of an @property. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -4207,7 +4756,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { << Name << D->getType() << FoundProp->getType(); Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } // FIXME: Check property attributes, getters, setters, etc.? @@ -4218,79 +4768,88 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { } } - // Import the type. - TypeSourceInfo *TSI = Importer.Import(D->getTypeSourceInfo()); - if (!TSI) - return nullptr; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToAtLoc, ToLParenLoc; + if (auto Imp = importSeq( + D->getType(), D->getTypeSourceInfo(), D->getAtLoc(), D->getLParenLoc())) + std::tie(ToType, ToTypeSourceInfo, ToAtLoc, ToLParenLoc) = *Imp; + else + return Imp.takeError(); // Create the new property. ObjCPropertyDecl *ToProperty; if (GetImportedOrCreateDecl( ToProperty, D, Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), Importer.Import(D->getAtLoc()), - Importer.Import(D->getLParenLoc()), Importer.Import(D->getType()), - TSI, D->getPropertyImplementation())) + Name.getAsIdentifierInfo(), ToAtLoc, + ToLParenLoc, ToType, + ToTypeSourceInfo, D->getPropertyImplementation())) return ToProperty; + Selector ToGetterName, ToSetterName; + SourceLocation ToGetterNameLoc, ToSetterNameLoc; + ObjCMethodDecl *ToGetterMethodDecl, *ToSetterMethodDecl; + ObjCIvarDecl *ToPropertyIvarDecl; + if (auto Imp = importSeq( + D->getGetterName(), D->getSetterName(), + D->getGetterNameLoc(), D->getSetterNameLoc(), + D->getGetterMethodDecl(), D->getSetterMethodDecl(), + D->getPropertyIvarDecl())) + std::tie( + ToGetterName, ToSetterName, + ToGetterNameLoc, ToSetterNameLoc, + ToGetterMethodDecl, ToSetterMethodDecl, + ToPropertyIvarDecl) = *Imp; + else + return Imp.takeError(); + ToProperty->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProperty); ToProperty->setPropertyAttributes(D->getPropertyAttributes()); ToProperty->setPropertyAttributesAsWritten( D->getPropertyAttributesAsWritten()); - ToProperty->setGetterName(Importer.Import(D->getGetterName()), - Importer.Import(D->getGetterNameLoc())); - ToProperty->setSetterName(Importer.Import(D->getSetterName()), - Importer.Import(D->getSetterNameLoc())); - ToProperty->setGetterMethodDecl( - cast_or_null<ObjCMethodDecl>(Importer.Import(D->getGetterMethodDecl()))); - ToProperty->setSetterMethodDecl( - cast_or_null<ObjCMethodDecl>(Importer.Import(D->getSetterMethodDecl()))); - ToProperty->setPropertyIvarDecl( - cast_or_null<ObjCIvarDecl>(Importer.Import(D->getPropertyIvarDecl()))); + ToProperty->setGetterName(ToGetterName, ToGetterNameLoc); + ToProperty->setSetterName(ToSetterName, ToSetterNameLoc); + ToProperty->setGetterMethodDecl(ToGetterMethodDecl); + ToProperty->setSetterMethodDecl(ToSetterMethodDecl); + ToProperty->setPropertyIvarDecl(ToPropertyIvarDecl); return ToProperty; } -Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { - auto *Property = cast_or_null<ObjCPropertyDecl>( - Importer.Import(D->getPropertyDecl())); - if (!Property) - return nullptr; - - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - if (!DC) - return nullptr; +ExpectedDecl +ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { + ObjCPropertyDecl *Property; + if (Error Err = importInto(Property, D->getPropertyDecl())) + return std::move(Err); - // Import the lexical declaration context. - DeclContext *LexicalDC = DC; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return nullptr; - } + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); - auto *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC); - if (!InImpl) - return nullptr; + auto *InImpl = cast<ObjCImplDecl>(LexicalDC); // Import the ivar (for an @synthesize). ObjCIvarDecl *Ivar = nullptr; - if (D->getPropertyIvarDecl()) { - Ivar = cast_or_null<ObjCIvarDecl>( - Importer.Import(D->getPropertyIvarDecl())); - if (!Ivar) - return nullptr; - } + if (Error Err = importInto(Ivar, D->getPropertyIvarDecl())) + return std::move(Err); ObjCPropertyImplDecl *ToImpl = InImpl->FindPropertyImplDecl(Property->getIdentifier(), Property->getQueryKind()); if (!ToImpl) { + SourceLocation ToBeginLoc, ToLocation, ToPropertyIvarDeclLoc; + if (auto Imp = importSeq( + D->getBeginLoc(), D->getLocation(), D->getPropertyIvarDeclLoc())) + std::tie(ToBeginLoc, ToLocation, ToPropertyIvarDeclLoc) = *Imp; + else + return Imp.takeError(); + if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC, - Importer.Import(D->getBeginLoc()), - Importer.Import(D->getLocation()), Property, + ToBeginLoc, + ToLocation, Property, D->getPropertyImplementation(), Ivar, - Importer.Import(D->getPropertyIvarDeclLoc()))) + ToPropertyIvarDeclLoc)) return ToImpl; ToImpl->setLexicalDeclContext(LexicalDC); @@ -4308,7 +4867,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { diag::note_odr_objc_property_impl_kind) << D->getPropertyDecl()->getDeclName() << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } // For @synthesize, check that we have the same @@ -4322,7 +4882,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { Importer.FromDiag(D->getPropertyIvarDeclLoc(), diag::note_odr_objc_synthesize_ivar_here) << D->getPropertyIvarDecl()->getDeclName(); - return nullptr; + + return make_error<ImportError>(ImportError::NameConflict); } // Merge the existing implementation with the new implementation. @@ -4332,41 +4893,46 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { return ToImpl; } -Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { +ExpectedDecl +ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { // For template arguments, we adopt the translation unit as our declaration // context. This context will be fixed when the actual template declaration // is created. // FIXME: Import default argument. + + ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + + ExpectedSLoc LocationOrErr = import(D->getLocation()); + if (!LocationOrErr) + return LocationOrErr.takeError(); + TemplateTypeParmDecl *ToD = nullptr; (void)GetImportedOrCreateDecl( ToD, D, Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), - Importer.Import(D->getBeginLoc()), Importer.Import(D->getLocation()), + *BeginLocOrErr, *LocationOrErr, D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()), D->wasDeclaredWithTypename(), D->isParameterPack()); return ToD; } -Decl * +ExpectedDecl ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { - // Import the name of this declaration. - DeclarationName Name = Importer.Import(D->getDeclName()); - if (D->getDeclName() && !Name) - return nullptr; - - // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); - - // Import the type of this declaration. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; - - // Import type-source information. - TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - if (D->getTypeSourceInfo() && !TInfo) - return nullptr; + DeclarationName ToDeclName; + SourceLocation ToLocation, ToInnerLocStart; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + if (auto Imp = importSeq( + D->getDeclName(), D->getLocation(), D->getType(), D->getTypeSourceInfo(), + D->getInnerLocStart())) + std::tie( + ToDeclName, ToLocation, ToType, ToTypeSourceInfo, + ToInnerLocStart) = *Imp; + else + return Imp.takeError(); // FIXME: Import default argument. @@ -4374,36 +4940,39 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { (void)GetImportedOrCreateDecl( ToD, D, Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), - Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(), - D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(), - TInfo); + ToInnerLocStart, ToLocation, D->getDepth(), + D->getPosition(), ToDeclName.getAsIdentifierInfo(), ToType, + D->isParameterPack(), ToTypeSourceInfo); return ToD; } -Decl * +ExpectedDecl ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { // Import the name of this declaration. - DeclarationName Name = Importer.Import(D->getDeclName()); - if (D->getDeclName() && !Name) - return nullptr; + auto NameOrErr = import(D->getDeclName()); + if (!NameOrErr) + return NameOrErr.takeError(); // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); + ExpectedSLoc LocationOrErr = import(D->getLocation()); + if (!LocationOrErr) + return LocationOrErr.takeError(); // Import template parameters. - TemplateParameterList *TemplateParams - = ImportTemplateParameterList(D->getTemplateParameters()); - if (!TemplateParams) - return nullptr; + auto TemplateParamsOrErr = ImportTemplateParameterList( + D->getTemplateParameters()); + if (!TemplateParamsOrErr) + return TemplateParamsOrErr.takeError(); // FIXME: Import default argument. TemplateTemplateParmDecl *ToD = nullptr; (void)GetImportedOrCreateDecl( ToD, D, Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), Loc, D->getDepth(), - D->getPosition(), D->isParameterPack(), Name.getAsIdentifierInfo(), - TemplateParams); + Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr, + D->getDepth(), D->getPosition(), D->isParameterPack(), + (*NameOrErr).getAsIdentifierInfo(), + *TemplateParamsOrErr); return ToD; } @@ -4418,7 +4987,7 @@ static ClassTemplateDecl *getDefinition(ClassTemplateDecl *D) { return TemplateWithDef; } -Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { +ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { bool IsFriend = D->getFriendObjectKind() != Decl::FOK_None; // If this record has a definition in the translation unit we're coming from, @@ -4427,12 +4996,11 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { auto *Definition = cast_or_null<CXXRecordDecl>(D->getTemplatedDecl()->getDefinition()); if (Definition && Definition != D->getTemplatedDecl() && !IsFriend) { - Decl *ImportedDef - = Importer.Import(Definition->getDescribedClassTemplate()); - if (!ImportedDef) - return nullptr; - - return Importer.MapImported(D, ImportedDef); + if (ExpectedDecl ImportedDefOrErr = import( + Definition->getDescribedClassTemplate())) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); } // Import the major distinguishing characteristics of this class template. @@ -4440,8 +5008,8 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -4490,26 +5058,25 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { } if (!Name) - return nullptr; + return make_error<ImportError>(ImportError::NameConflict); } CXXRecordDecl *FromTemplated = D->getTemplatedDecl(); // Create the declaration that is being templated. - auto *ToTemplated = cast_or_null<CXXRecordDecl>( - Importer.Import(FromTemplated)); - if (!ToTemplated) - return nullptr; + CXXRecordDecl *ToTemplated; + if (Error Err = importInto(ToTemplated, FromTemplated)) + return std::move(Err); // Create the class template declaration itself. - TemplateParameterList *TemplateParams = - ImportTemplateParameterList(D->getTemplateParameters()); - if (!TemplateParams) - return nullptr; + auto TemplateParamsOrErr = ImportTemplateParameterList( + D->getTemplateParameters()); + if (!TemplateParamsOrErr) + return TemplateParamsOrErr.takeError(); ClassTemplateDecl *D2; if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name, - TemplateParams, ToTemplated)) + *TemplateParamsOrErr, ToTemplated)) return D2; ToTemplated->setDescribedClassTemplate(D2); @@ -4534,48 +5101,33 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { return D2; } -Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( +ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { // If this record has a definition in the translation unit we're coming from, // but this particular declaration is not that definition, import the // definition and map to that. TagDecl *Definition = D->getDefinition(); if (Definition && Definition != D) { - Decl *ImportedDef = Importer.Import(Definition); - if (!ImportedDef) - return nullptr; - - return Importer.MapImported(D, ImportedDef); + if (ExpectedDecl ImportedDefOrErr = import(Definition)) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); } - auto *ClassTemplate = - cast_or_null<ClassTemplateDecl>(Importer.Import( - D->getSpecializedTemplate())); - if (!ClassTemplate) - return nullptr; + ClassTemplateDecl *ClassTemplate; + if (Error Err = importInto(ClassTemplate, D->getSpecializedTemplate())) + return std::move(Err); // Import the context of this declaration. - DeclContext *DC = ClassTemplate->getDeclContext(); - if (!DC) - return nullptr; - - DeclContext *LexicalDC = DC; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return nullptr; - } - - // Import the location of this declaration. - SourceLocation StartLoc = Importer.Import(D->getBeginLoc()); - SourceLocation IdLoc = Importer.Import(D->getLocation()); + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); // Import template arguments. SmallVector<TemplateArgument, 2> TemplateArgs; - if (ImportTemplateArguments(D->getTemplateArgs().data(), - D->getTemplateArgs().size(), - TemplateArgs)) - return nullptr; + if (Error Err = ImportTemplateArguments( + D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) + return std::move(Err); // Try to find an existing specialization with these template arguments. void *InsertPos = nullptr; @@ -4602,13 +5154,21 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Import those those default field initializers which have been // instantiated in the "From" context, but not in the "To" context. - for (auto *FromField : D->fields()) - Importer.Import(FromField); + for (auto *FromField : D->fields()) { + auto ToOrErr = import(FromField); + if (!ToOrErr) + // FIXME: return the error? + consumeError(ToOrErr.takeError()); + } // Import those methods which have been instantiated in the // "From" context, but not in the "To" context. - for (CXXMethodDecl *FromM : D->methods()) - Importer.Import(FromM); + for (CXXMethodDecl *FromM : D->methods()) { + auto ToOrErr = import(FromM); + if (!ToOrErr) + // FIXME: return the error? + consumeError(ToOrErr.takeError()); + } // TODO Import instantiated default arguments. // TODO Import instantiated exception specifications. @@ -4621,27 +5181,36 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( } else { // We either couldn't find any previous specialization in the "To" // context, or we found one but without definition. Let's create a // new specialization and register that at the class template. + + // Import the location of this declaration. + ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + ExpectedSLoc IdLocOrErr = import(D->getLocation()); + if (!IdLocOrErr) + return IdLocOrErr.takeError(); + if (PartialSpec) { // Import TemplateArgumentListInfo. TemplateArgumentListInfo ToTAInfo; const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); - if (ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) - return nullptr; + if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) + return std::move(Err); - QualType CanonInjType = Importer.Import( - PartialSpec->getInjectedSpecializationType()); - if (CanonInjType.isNull()) - return nullptr; + QualType CanonInjType; + if (Error Err = importInto( + CanonInjType, PartialSpec->getInjectedSpecializationType())) + return std::move(Err); CanonInjType = CanonInjType.getCanonicalType(); - TemplateParameterList *ToTPList = ImportTemplateParameterList( - PartialSpec->getTemplateParameters()); - if (!ToTPList && PartialSpec->getTemplateParameters()) - return nullptr; + auto ToTPListOrErr = ImportTemplateParameterList( + PartialSpec->getTemplateParameters()); + if (!ToTPListOrErr) + return ToTPListOrErr.takeError(); if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( - D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, - IdLoc, ToTPList, ClassTemplate, + D2, D, Importer.getToContext(), D->getTagKind(), DC, + *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, ClassTemplate, llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), ToTAInfo, CanonInjType, cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) @@ -4656,8 +5225,9 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( } else { // Not a partial specialization. if (GetImportedOrCreateDecl( - D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, - IdLoc, ClassTemplate, TemplateArgs, PrevDecl)) + D2, D, Importer.getToContext(), D->getTagKind(), DC, + *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs, + PrevDecl)) return D2; // Update InsertPos, because preceding import calls may have invalidated @@ -4670,22 +5240,34 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( D2->setSpecializationKind(D->getSpecializationKind()); // Import the qualifier, if any. - D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); + if (auto LocOrErr = import(D->getQualifierLoc())) + D2->setQualifierInfo(*LocOrErr); + else + return LocOrErr.takeError(); if (auto *TSI = D->getTypeAsWritten()) { - TypeSourceInfo *TInfo = Importer.Import(TSI); - if (!TInfo) - return nullptr; - D2->setTypeAsWritten(TInfo); - D2->setTemplateKeywordLoc(Importer.Import(D->getTemplateKeywordLoc())); - D2->setExternLoc(Importer.Import(D->getExternLoc())); + if (auto TInfoOrErr = import(TSI)) + D2->setTypeAsWritten(*TInfoOrErr); + else + return TInfoOrErr.takeError(); + + if (auto LocOrErr = import(D->getTemplateKeywordLoc())) + D2->setTemplateKeywordLoc(*LocOrErr); + else + return LocOrErr.takeError(); + + if (auto LocOrErr = import(D->getExternLoc())) + D2->setExternLoc(*LocOrErr); + else + return LocOrErr.takeError(); } - SourceLocation POI = Importer.Import(D->getPointOfInstantiation()); - if (POI.isValid()) - D2->setPointOfInstantiation(POI); - else if (D->getPointOfInstantiation().isValid()) - return nullptr; + if (D->getPointOfInstantiation().isValid()) { + if (auto POIOrErr = import(D->getPointOfInstantiation())) + D2->setPointOfInstantiation(*POIOrErr); + else + return POIOrErr.takeError(); + } D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); @@ -4697,13 +5279,14 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( LexicalDC->addDeclInternal(D2); } } - if (D->isCompleteDefinition() && ImportDefinition(D, D2)) - return nullptr; + if (D->isCompleteDefinition()) + if (Error Err = ImportDefinition(D, D2)) + return std::move(Err); return D2; } -Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { +ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // If this variable has a definition in the translation unit we're coming // from, // but this particular declaration is not that definition, import the @@ -4711,11 +5294,11 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { auto *Definition = cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition()); if (Definition && Definition != D->getTemplatedDecl()) { - Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate()); - if (!ImportedDef) - return nullptr; - - return Importer.MapImported(D, ImportedDef); + if (ExpectedDecl ImportedDefOrErr = import( + Definition->getDescribedVarTemplate())) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); } // Import the major distinguishing characteristics of this variable template. @@ -4723,8 +5306,8 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -4739,7 +5322,7 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { continue; Decl *Found = FoundDecl; - if (auto *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) { + if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) { if (IsStructuralMatch(D, FoundTemplate)) { // The variable templates structurally match; call it the same template. Importer.MapImported(D->getTemplatedDecl(), @@ -4758,29 +5341,32 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { } if (!Name) - return nullptr; + // FIXME: Is it possible to get other error than name conflict? + // (Put this `if` into the previous `if`?) + return make_error<ImportError>(ImportError::NameConflict); VarDecl *DTemplated = D->getTemplatedDecl(); // Import the type. - QualType T = Importer.Import(DTemplated->getType()); - if (T.isNull()) - return nullptr; + // FIXME: Value not used? + ExpectedType TypeOrErr = import(DTemplated->getType()); + if (!TypeOrErr) + return TypeOrErr.takeError(); // Create the declaration that is being templated. - auto *ToTemplated = dyn_cast_or_null<VarDecl>(Importer.Import(DTemplated)); - if (!ToTemplated) - return nullptr; + VarDecl *ToTemplated; + if (Error Err = importInto(ToTemplated, DTemplated)) + return std::move(Err); // Create the variable template declaration itself. - TemplateParameterList *TemplateParams = - ImportTemplateParameterList(D->getTemplateParameters()); - if (!TemplateParams) - return nullptr; + auto TemplateParamsOrErr = ImportTemplateParameterList( + D->getTemplateParameters()); + if (!TemplateParamsOrErr) + return TemplateParamsOrErr.takeError(); VarTemplateDecl *ToVarTD; if (GetImportedOrCreateDecl(ToVarTD, D, Importer.getToContext(), DC, Loc, - Name, TemplateParams, ToTemplated)) + Name, *TemplateParamsOrErr, ToTemplated)) return ToVarTD; ToTemplated->setDescribedVarTemplate(ToVarTD); @@ -4797,46 +5383,42 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { return ToVarTD; } -Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( +ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *D) { // If this record has a definition in the translation unit we're coming from, // but this particular declaration is not that definition, import the // definition and map to that. VarDecl *Definition = D->getDefinition(); if (Definition && Definition != D) { - Decl *ImportedDef = Importer.Import(Definition); - if (!ImportedDef) - return nullptr; - - return Importer.MapImported(D, ImportedDef); + if (ExpectedDecl ImportedDefOrErr = import(Definition)) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); } - auto *VarTemplate = cast_or_null<VarTemplateDecl>( - Importer.Import(D->getSpecializedTemplate())); - if (!VarTemplate) - return nullptr; + VarTemplateDecl *VarTemplate; + if (Error Err = importInto(VarTemplate, D->getSpecializedTemplate())) + return std::move(Err); // Import the context of this declaration. - DeclContext *DC = VarTemplate->getDeclContext(); - if (!DC) - return nullptr; - - DeclContext *LexicalDC = DC; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return nullptr; - } + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); // Import the location of this declaration. - SourceLocation StartLoc = Importer.Import(D->getBeginLoc()); - SourceLocation IdLoc = Importer.Import(D->getLocation()); + ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + + auto IdLocOrErr = import(D->getLocation()); + if (!IdLocOrErr) + return IdLocOrErr.takeError(); // Import template arguments. SmallVector<TemplateArgument, 2> TemplateArgs; - if (ImportTemplateArguments(D->getTemplateArgs().data(), - D->getTemplateArgs().size(), TemplateArgs)) - return nullptr; + if (Error Err = ImportTemplateArguments( + D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) + return std::move(Err); // Try to find an existing specialization with these template arguments. void *InsertPos = nullptr; @@ -4859,17 +5441,18 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( } } else { // Import the type. - QualType T = Importer.Import(D->getType()); - if (T.isNull()) - return nullptr; + QualType T; + if (Error Err = importInto(T, D->getType())) + return std::move(Err); - TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - if (D->getTypeSourceInfo() && !TInfo) - return nullptr; + auto TInfoOrErr = import(D->getTypeSourceInfo()); + if (!TInfoOrErr) + return TInfoOrErr.takeError(); TemplateArgumentListInfo ToTAInfo; - if (ImportTemplateArgumentListInfo(D->getTemplateArgsInfo(), ToTAInfo)) - return nullptr; + if (Error Err = ImportTemplateArgumentListInfo( + D->getTemplateArgsInfo(), ToTAInfo)) + return std::move(Err); using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; // Create a new specialization. @@ -4878,41 +5461,47 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( TemplateArgumentListInfo ArgInfos; const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten(); // NOTE: FromTAArgsAsWritten and template parameter list are non-null. - if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ArgInfos)) - return nullptr; + if (Error Err = ImportTemplateArgumentListInfo( + *FromTAArgsAsWritten, ArgInfos)) + return std::move(Err); - TemplateParameterList *ToTPList = ImportTemplateParameterList( - FromPartial->getTemplateParameters()); - if (!ToTPList) - return nullptr; + auto ToTPListOrErr = ImportTemplateParameterList( + FromPartial->getTemplateParameters()); + if (!ToTPListOrErr) + return ToTPListOrErr.takeError(); PartVarSpecDecl *ToPartial; if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, - StartLoc, IdLoc, ToTPList, VarTemplate, T, - TInfo, D->getStorageClass(), TemplateArgs, - ArgInfos)) + *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, + VarTemplate, T, *TInfoOrErr, + D->getStorageClass(), TemplateArgs, ArgInfos)) return ToPartial; - auto *FromInst = FromPartial->getInstantiatedFromMember(); - auto *ToInst = cast_or_null<PartVarSpecDecl>(Importer.Import(FromInst)); - if (FromInst && !ToInst) - return nullptr; + if (Expected<PartVarSpecDecl *> ToInstOrErr = import( + FromPartial->getInstantiatedFromMember())) + ToPartial->setInstantiatedFromMember(*ToInstOrErr); + else + return ToInstOrErr.takeError(); - ToPartial->setInstantiatedFromMember(ToInst); if (FromPartial->isMemberSpecialization()) ToPartial->setMemberSpecialization(); D2 = ToPartial; + } else { // Full specialization - if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, StartLoc, - IdLoc, VarTemplate, T, TInfo, + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, + *BeginLocOrErr, *IdLocOrErr, VarTemplate, + T, *TInfoOrErr, D->getStorageClass(), TemplateArgs)) return D2; } - SourceLocation POI = D->getPointOfInstantiation(); - if (POI.isValid()) - D2->setPointOfInstantiation(Importer.Import(POI)); + if (D->getPointOfInstantiation().isValid()) { + if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation())) + D2->setPointOfInstantiation(*POIOrErr); + else + return POIOrErr.takeError(); + } D2->setSpecializationKind(D->getSpecializationKind()); D2->setTemplateArgsInfo(ToTAInfo); @@ -4921,7 +5510,10 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( VarTemplate->AddSpecialization(D2, InsertPos); // Import the qualifier, if any. - D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); + if (auto LocOrErr = import(D->getQualifierLoc())) + D2->setQualifierInfo(*LocOrErr); + else + return LocOrErr.takeError(); if (D->isConstexpr()) D2->setConstexpr(true); @@ -4933,20 +5525,21 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( D2->setAccess(D->getAccess()); } - if (ImportInitializer(D, D2)) - return nullptr; + if (Error Err = ImportInitializer(D, D2)) + return std::move(Err); return D2; } -Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { +ExpectedDecl +ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) - return nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); if (ToD) return ToD; @@ -4961,7 +5554,8 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (auto *FoundFunction = dyn_cast<FunctionTemplateDecl>(FoundDecl)) { + if (auto *FoundFunction = + dyn_cast<FunctionTemplateDecl>(FoundDecl)) { if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { if (IsStructuralMatch(D, FoundFunction)) { @@ -4971,22 +5565,22 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { } } } + // TODO: handle conflicting names } } - TemplateParameterList *Params = - ImportTemplateParameterList(D->getTemplateParameters()); - if (!Params) - return nullptr; + auto ParamsOrErr = ImportTemplateParameterList( + D->getTemplateParameters()); + if (!ParamsOrErr) + return ParamsOrErr.takeError(); - auto *TemplatedFD = - cast_or_null<FunctionDecl>(Importer.Import(D->getTemplatedDecl())); - if (!TemplatedFD) - return nullptr; + FunctionDecl *TemplatedFD; + if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl())) + return std::move(Err); FunctionTemplateDecl *ToFunc; if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, - Params, TemplatedFD)) + *ParamsOrErr, TemplatedFD)) return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); @@ -5001,2012 +5595,2084 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // Import Statements //---------------------------------------------------------------------------- -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) { +ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) { Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node) << S->getStmtClassName(); - return nullptr; + return make_error<ImportError>(ImportError::UnsupportedConstruct); } -Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { + +ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { SmallVector<IdentifierInfo *, 4> Names; for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); // ToII is nullptr when no symbolic name is given for output operand // see ParseStmtAsm::ParseAsmOperandsOpt - if (!ToII && S->getOutputIdentifier(I)) - return nullptr; Names.push_back(ToII); } + for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { IdentifierInfo *ToII = Importer.Import(S->getInputIdentifier(I)); // ToII is nullptr when no symbolic name is given for input operand // see ParseStmtAsm::ParseAsmOperandsOpt - if (!ToII && S->getInputIdentifier(I)) - return nullptr; Names.push_back(ToII); } SmallVector<StringLiteral *, 4> Clobbers; for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) { - auto *Clobber = cast_or_null<StringLiteral>( - Importer.Import(S->getClobberStringLiteral(I))); - if (!Clobber) - return nullptr; - Clobbers.push_back(Clobber); + if (auto ClobberOrErr = import(S->getClobberStringLiteral(I))) + Clobbers.push_back(*ClobberOrErr); + else + return ClobberOrErr.takeError(); + } SmallVector<StringLiteral *, 4> Constraints; for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { - auto *Output = cast_or_null<StringLiteral>( - Importer.Import(S->getOutputConstraintLiteral(I))); - if (!Output) - return nullptr; - Constraints.push_back(Output); + if (auto OutputOrErr = import(S->getOutputConstraintLiteral(I))) + Constraints.push_back(*OutputOrErr); + else + return OutputOrErr.takeError(); } for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { - auto *Input = cast_or_null<StringLiteral>( - Importer.Import(S->getInputConstraintLiteral(I))); - if (!Input) - return nullptr; - Constraints.push_back(Input); + if (auto InputOrErr = import(S->getInputConstraintLiteral(I))) + Constraints.push_back(*InputOrErr); + else + return InputOrErr.takeError(); } SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs()); - if (ImportContainerChecked(S->outputs(), Exprs)) - return nullptr; - - if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs())) - return nullptr; - - auto *AsmStr = cast_or_null<StringLiteral>( - Importer.Import(S->getAsmString())); - if (!AsmStr) - return nullptr; + if (Error Err = ImportContainerChecked(S->outputs(), Exprs)) + return std::move(Err); + + if (Error Err = ImportArrayChecked( + S->inputs(), Exprs.begin() + S->getNumOutputs())) + return std::move(Err); + + ExpectedSLoc AsmLocOrErr = import(S->getAsmLoc()); + if (!AsmLocOrErr) + return AsmLocOrErr.takeError(); + auto AsmStrOrErr = import(S->getAsmString()); + if (!AsmStrOrErr) + return AsmStrOrErr.takeError(); + ExpectedSLoc RParenLocOrErr = import(S->getRParenLoc()); + if (!RParenLocOrErr) + return RParenLocOrErr.takeError(); return new (Importer.getToContext()) GCCAsmStmt( - Importer.getToContext(), - Importer.Import(S->getAsmLoc()), - S->isSimple(), - S->isVolatile(), - S->getNumOutputs(), - S->getNumInputs(), - Names.data(), - Constraints.data(), - Exprs.data(), - AsmStr, - S->getNumClobbers(), - Clobbers.data(), - Importer.Import(S->getRParenLoc())); -} - -Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) { - DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup()); - for (auto *ToD : ToDG) { - if (!ToD) - return nullptr; - } - SourceLocation ToStartLoc = Importer.Import(S->getBeginLoc()); - SourceLocation ToEndLoc = Importer.Import(S->getEndLoc()); - return new (Importer.getToContext()) DeclStmt(ToDG, ToStartLoc, ToEndLoc); -} + Importer.getToContext(), + *AsmLocOrErr, + S->isSimple(), + S->isVolatile(), + S->getNumOutputs(), + S->getNumInputs(), + Names.data(), + Constraints.data(), + Exprs.data(), + *AsmStrOrErr, + S->getNumClobbers(), + Clobbers.data(), + *RParenLocOrErr); +} + +ExpectedStmt ASTNodeImporter::VisitDeclStmt(DeclStmt *S) { + auto Imp = importSeq(S->getDeclGroup(), S->getBeginLoc(), S->getEndLoc()); + if (!Imp) + return Imp.takeError(); + + DeclGroupRef ToDG; + SourceLocation ToBeginLoc, ToEndLoc; + std::tie(ToDG, ToBeginLoc, ToEndLoc) = *Imp; + + return new (Importer.getToContext()) DeclStmt(ToDG, ToBeginLoc, ToEndLoc); +} + +ExpectedStmt ASTNodeImporter::VisitNullStmt(NullStmt *S) { + ExpectedSLoc ToSemiLocOrErr = import(S->getSemiLoc()); + if (!ToSemiLocOrErr) + return ToSemiLocOrErr.takeError(); + return new (Importer.getToContext()) NullStmt( + *ToSemiLocOrErr, S->hasLeadingEmptyMacro()); +} + +ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { + SmallVector<Stmt *, 8> ToStmts(S->size()); -Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) { - SourceLocation ToSemiLoc = Importer.Import(S->getSemiLoc()); - return new (Importer.getToContext()) NullStmt(ToSemiLoc, - S->hasLeadingEmptyMacro()); -} + if (Error Err = ImportContainerChecked(S->body(), ToStmts)) + return std::move(Err); -Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { - SmallVector<Stmt *, 8> ToStmts(S->size()); + ExpectedSLoc ToLBracLocOrErr = import(S->getLBracLoc()); + if (!ToLBracLocOrErr) + return ToLBracLocOrErr.takeError(); - if (ImportContainerChecked(S->body(), ToStmts)) - return nullptr; + ExpectedSLoc ToRBracLocOrErr = import(S->getRBracLoc()); + if (!ToRBracLocOrErr) + return ToRBracLocOrErr.takeError(); - SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc()); - SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc()); - return CompoundStmt::Create(Importer.getToContext(), ToStmts, ToLBraceLoc, - ToRBraceLoc); + return CompoundStmt::Create( + Importer.getToContext(), ToStmts, + *ToLBracLocOrErr, *ToRBracLocOrErr); } -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; - Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); - if (!ToSubStmt && S->getSubStmt()) - return nullptr; - SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc()); - SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc()); - SourceLocation ToColonLoc = Importer.Import(S->getColonLoc()); - auto *ToStmt = new (Importer.getToContext()) - CaseStmt(ToLHS, ToRHS, ToCaseLoc, ToEllipsisLoc, ToColonLoc); +ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { + auto Imp = importSeq( + S->getLHS(), S->getRHS(), S->getSubStmt(), S->getCaseLoc(), + S->getEllipsisLoc(), S->getColonLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToLHS, *ToRHS; + Stmt *ToSubStmt; + SourceLocation ToCaseLoc, ToEllipsisLoc, ToColonLoc; + std::tie(ToLHS, ToRHS, ToSubStmt, ToCaseLoc, ToEllipsisLoc, ToColonLoc) = + *Imp; + + auto *ToStmt = CaseStmt::Create(Importer.getToContext(), ToLHS, ToRHS, + ToCaseLoc, ToEllipsisLoc, ToColonLoc); ToStmt->setSubStmt(ToSubStmt); + return ToStmt; } -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); -} +ExpectedStmt ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) { + auto Imp = importSeq(S->getDefaultLoc(), S->getColonLoc(), S->getSubStmt()); + if (!Imp) + return Imp.takeError(); -Stmt *ASTNodeImporter::VisitLabelStmt(LabelStmt *S) { - SourceLocation ToIdentLoc = Importer.Import(S->getIdentLoc()); - auto *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); -} + SourceLocation ToDefaultLoc, ToColonLoc; + Stmt *ToSubStmt; + std::tie(ToDefaultLoc, ToColonLoc, ToSubStmt) = *Imp; -Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) { - SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc()); - ArrayRef<const Attr*> FromAttrs(S->getAttrs()); - SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size()); - if (ImportContainerChecked(FromAttrs, ToAttrs)) - return nullptr; - Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); - if (!ToSubStmt && S->getSubStmt()) - return nullptr; - return AttributedStmt::Create(Importer.getToContext(), ToAttrLoc, - ToAttrs, ToSubStmt); + return new (Importer.getToContext()) DefaultStmt( + ToDefaultLoc, ToColonLoc, ToSubStmt); } -Stmt *ASTNodeImporter::VisitIfStmt(IfStmt *S) { - SourceLocation ToIfLoc = Importer.Import(S->getIfLoc()); - Stmt *ToInit = Importer.Import(S->getInit()); - if (!ToInit && S->getInit()) - return nullptr; - 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, S->isConstexpr(), - ToInit, - ToConditionVariable, - ToCondition, ToThenStmt, - ToElseLoc, ToElseStmt); +ExpectedStmt ASTNodeImporter::VisitLabelStmt(LabelStmt *S) { + auto Imp = importSeq(S->getIdentLoc(), S->getDecl(), S->getSubStmt()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToIdentLoc; + LabelDecl *ToLabelDecl; + Stmt *ToSubStmt; + std::tie(ToIdentLoc, ToLabelDecl, ToSubStmt) = *Imp; + + return new (Importer.getToContext()) LabelStmt( + ToIdentLoc, ToLabelDecl, ToSubStmt); } -Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { - Stmt *ToInit = Importer.Import(S->getInit()); - if (!ToInit && S->getInit()) - return nullptr; - 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; - auto *ToStmt = new (Importer.getToContext()) SwitchStmt( - Importer.getToContext(), ToInit, - ToConditionVariable, ToCondition); - Stmt *ToBody = Importer.Import(S->getBody()); - if (!ToBody && S->getBody()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) { + ExpectedSLoc ToAttrLocOrErr = import(S->getAttrLoc()); + if (!ToAttrLocOrErr) + return ToAttrLocOrErr.takeError(); + ArrayRef<const Attr*> FromAttrs(S->getAttrs()); + SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size()); + if (Error Err = ImportContainerChecked(FromAttrs, ToAttrs)) + return std::move(Err); + ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt()); + if (!ToSubStmtOrErr) + return ToSubStmtOrErr.takeError(); + + return AttributedStmt::Create( + Importer.getToContext(), *ToAttrLocOrErr, ToAttrs, *ToSubStmtOrErr); +} + +ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) { + auto Imp = importSeq( + S->getIfLoc(), S->getInit(), S->getConditionVariable(), S->getCond(), + S->getThen(), S->getElseLoc(), S->getElse()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToIfLoc, ToElseLoc; + Stmt *ToInit, *ToThen, *ToElse; + VarDecl *ToConditionVariable; + Expr *ToCond; + std::tie( + ToIfLoc, ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc, ToElse) = + *Imp; + + return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(), + ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc, + ToElse); +} + +ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { + auto Imp = importSeq( + S->getInit(), S->getConditionVariable(), S->getCond(), + S->getBody(), S->getSwitchLoc()); + if (!Imp) + return Imp.takeError(); + + Stmt *ToInit, *ToBody; + VarDecl *ToConditionVariable; + Expr *ToCond; + SourceLocation ToSwitchLoc; + std::tie(ToInit, ToConditionVariable, ToCond, ToBody, ToSwitchLoc) = *Imp; + + auto *ToStmt = SwitchStmt::Create(Importer.getToContext(), ToInit, + ToConditionVariable, ToCond); ToStmt->setBody(ToBody); - ToStmt->setSwitchLoc(Importer.Import(S->getSwitchLoc())); + ToStmt->setSwitchLoc(ToSwitchLoc); + // Now we have to re-chain the cases. SwitchCase *LastChainedSwitchCase = nullptr; for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr; SC = SC->getNextSwitchCase()) { - auto *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC)); - if (!ToSC) - return nullptr; + Expected<SwitchCase *> ToSCOrErr = import(SC); + if (!ToSCOrErr) + return ToSCOrErr.takeError(); if (LastChainedSwitchCase) - LastChainedSwitchCase->setNextSwitchCase(ToSC); + LastChainedSwitchCase->setNextSwitchCase(*ToSCOrErr); else - ToStmt->setSwitchCaseList(ToSC); - LastChainedSwitchCase = ToSC; + ToStmt->setSwitchCaseList(*ToSCOrErr); + LastChainedSwitchCase = *ToSCOrErr; } + 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); +ExpectedStmt ASTNodeImporter::VisitWhileStmt(WhileStmt *S) { + auto Imp = importSeq( + S->getConditionVariable(), S->getCond(), S->getBody(), S->getWhileLoc()); + if (!Imp) + return Imp.takeError(); + + VarDecl *ToConditionVariable; + Expr *ToCond; + Stmt *ToBody; + SourceLocation ToWhileLoc; + std::tie(ToConditionVariable, ToCond, ToBody, ToWhileLoc) = *Imp; + + return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond, + 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); +ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) { + auto Imp = importSeq( + S->getBody(), S->getCond(), S->getDoLoc(), S->getWhileLoc(), + S->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + Stmt *ToBody; + Expr *ToCond; + SourceLocation ToDoLoc, ToWhileLoc, ToRParenLoc; + std::tie(ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc) = *Imp; + + return new (Importer.getToContext()) DoStmt( + ToBody, ToCond, 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); +ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) { + auto Imp = importSeq( + S->getInit(), S->getCond(), S->getConditionVariable(), S->getInc(), + S->getBody(), S->getForLoc(), S->getLParenLoc(), S->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + Stmt *ToInit; + Expr *ToCond, *ToInc; + VarDecl *ToConditionVariable; + Stmt *ToBody; + SourceLocation ToForLoc, ToLParenLoc, ToRParenLoc; + std::tie( + ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, + ToLParenLoc, ToRParenLoc) = *Imp; + + return new (Importer.getToContext()) ForStmt( + Importer.getToContext(), + ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, ToLParenLoc, + ToRParenLoc); } -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); +ExpectedStmt ASTNodeImporter::VisitGotoStmt(GotoStmt *S) { + auto Imp = importSeq(S->getLabel(), S->getGotoLoc(), S->getLabelLoc()); + if (!Imp) + return Imp.takeError(); + + LabelDecl *ToLabel; + SourceLocation ToGotoLoc, ToLabelLoc; + std::tie(ToLabel, ToGotoLoc, ToLabelLoc) = *Imp; + + return new (Importer.getToContext()) GotoStmt( + ToLabel, ToGotoLoc, ToLabelLoc); } -Stmt *ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) { - SourceLocation ToContinueLoc = Importer.Import(S->getContinueLoc()); - return new (Importer.getToContext()) ContinueStmt(ToContinueLoc); +ExpectedStmt ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { + auto Imp = importSeq(S->getGotoLoc(), S->getStarLoc(), S->getTarget()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToGotoLoc, ToStarLoc; + Expr *ToTarget; + std::tie(ToGotoLoc, ToStarLoc, ToTarget) = *Imp; + + return new (Importer.getToContext()) IndirectGotoStmt( + ToGotoLoc, ToStarLoc, ToTarget); } -Stmt *ASTNodeImporter::VisitBreakStmt(BreakStmt *S) { - SourceLocation ToBreakLoc = Importer.Import(S->getBreakLoc()); - return new (Importer.getToContext()) BreakStmt(ToBreakLoc); +ExpectedStmt ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) { + ExpectedSLoc ToContinueLocOrErr = import(S->getContinueLoc()); + if (!ToContinueLocOrErr) + return ToContinueLocOrErr.takeError(); + return new (Importer.getToContext()) ContinueStmt(*ToContinueLocOrErr); } -Stmt *ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) { - SourceLocation ToRetLoc = Importer.Import(S->getReturnLoc()); - Expr *ToRetExpr = Importer.Import(S->getRetValue()); - if (!ToRetExpr && S->getRetValue()) - return nullptr; - auto *NRVOCandidate = const_cast<VarDecl *>(S->getNRVOCandidate()); - auto *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate)); - if (!ToNRVOCandidate && NRVOCandidate) - return nullptr; - return new (Importer.getToContext()) ReturnStmt(ToRetLoc, ToRetExpr, - ToNRVOCandidate); +ExpectedStmt ASTNodeImporter::VisitBreakStmt(BreakStmt *S) { + auto ToBreakLocOrErr = import(S->getBreakLoc()); + if (!ToBreakLocOrErr) + return ToBreakLocOrErr.takeError(); + return new (Importer.getToContext()) BreakStmt(*ToBreakLocOrErr); } -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); +ExpectedStmt ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) { + auto Imp = importSeq( + S->getReturnLoc(), S->getRetValue(), S->getNRVOCandidate()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToReturnLoc; + Expr *ToRetValue; + const VarDecl *ToNRVOCandidate; + std::tie(ToReturnLoc, ToRetValue, ToNRVOCandidate) = *Imp; + + return ReturnStmt::Create(Importer.getToContext(), ToReturnLoc, ToRetValue, + ToNRVOCandidate); } -Stmt *ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) { - SourceLocation ToTryLoc = Importer.Import(S->getTryLoc()); - Stmt *ToTryBlock = Importer.Import(S->getTryBlock()); - if (!ToTryBlock && S->getTryBlock()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) { + auto Imp = importSeq( + S->getCatchLoc(), S->getExceptionDecl(), S->getHandlerBlock()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToCatchLoc; + VarDecl *ToExceptionDecl; + Stmt *ToHandlerBlock; + std::tie(ToCatchLoc, ToExceptionDecl, ToHandlerBlock) = *Imp; + + return new (Importer.getToContext()) CXXCatchStmt ( + ToCatchLoc, ToExceptionDecl, ToHandlerBlock); +} + +ExpectedStmt ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) { + ExpectedSLoc ToTryLocOrErr = import(S->getTryLoc()); + if (!ToTryLocOrErr) + return ToTryLocOrErr.takeError(); + + ExpectedStmt ToTryBlockOrErr = import(S->getTryBlock()); + if (!ToTryBlockOrErr) + return ToTryBlockOrErr.takeError(); + 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; + if (auto ToHandlerOrErr = import(FromHandler)) + ToHandlers[HI] = *ToHandlerOrErr; else - return nullptr; - } - return CXXTryStmt::Create(Importer.getToContext(), ToTryLoc, ToTryBlock, - ToHandlers); + return ToHandlerOrErr.takeError(); + } + + return CXXTryStmt::Create( + Importer.getToContext(), *ToTryLocOrErr,*ToTryBlockOrErr, ToHandlers); +} + +ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { + auto Imp1 = importSeq( + S->getInit(), S->getRangeStmt(), S->getBeginStmt(), S->getEndStmt(), + S->getCond(), S->getInc(), S->getLoopVarStmt(), S->getBody()); + if (!Imp1) + return Imp1.takeError(); + auto Imp2 = importSeq( + S->getForLoc(), S->getCoawaitLoc(), S->getColonLoc(), S->getRParenLoc()); + if (!Imp2) + return Imp2.takeError(); + + DeclStmt *ToRangeStmt, *ToBeginStmt, *ToEndStmt, *ToLoopVarStmt; + Expr *ToCond, *ToInc; + Stmt *ToInit, *ToBody; + std::tie( + ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt, + ToBody) = *Imp1; + SourceLocation ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc; + std::tie(ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc) = *Imp2; + + return new (Importer.getToContext()) CXXForRangeStmt( + ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt, + ToBody, ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc); +} + +ExpectedStmt +ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { + auto Imp = importSeq( + S->getElement(), S->getCollection(), S->getBody(), + S->getForLoc(), S->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + Stmt *ToElement, *ToBody; + Expr *ToCollection; + SourceLocation ToForLoc, ToRParenLoc; + std::tie(ToElement, ToCollection, ToBody, ToForLoc, ToRParenLoc) = *Imp; + + return new (Importer.getToContext()) ObjCForCollectionStmt(ToElement, + ToCollection, + ToBody, + ToForLoc, + ToRParenLoc); } -Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { - auto *ToInit = dyn_cast_or_null<Stmt>(Importer.Import(S->getInit())); - if (!ToInit && S->getInit()) - return nullptr; - auto *ToRange = - dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt())); - if (!ToRange && S->getRangeStmt()) - return nullptr; - auto *ToBegin = - dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginStmt())); - if (!ToBegin && S->getBeginStmt()) - return nullptr; - auto *ToEnd = - dyn_cast_or_null<DeclStmt>(Importer.Import(S->getEndStmt())); - if (!ToEnd && S->getEndStmt()) - 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; - auto *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 ToCoawaitLoc = Importer.Import(S->getCoawaitLoc()); - SourceLocation ToColonLoc = Importer.Import(S->getColonLoc()); - SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc()); - return new (Importer.getToContext()) - CXXForRangeStmt(ToInit, ToRange, ToBegin, ToEnd, ToCond, ToInc, ToLoopVar, - ToBody, ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc); -} +ExpectedStmt ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { + auto Imp = importSeq( + S->getAtCatchLoc(), S->getRParenLoc(), S->getCatchParamDecl(), + S->getCatchBody()); + if (!Imp) + return Imp.takeError(); -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); -} + SourceLocation ToAtCatchLoc, ToRParenLoc; + VarDecl *ToCatchParamDecl; + Stmt *ToCatchBody; + std::tie(ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody) = *Imp; -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); + return new (Importer.getToContext()) ObjCAtCatchStmt ( + ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody); } -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); +ExpectedStmt ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { + ExpectedSLoc ToAtFinallyLocOrErr = import(S->getAtFinallyLoc()); + if (!ToAtFinallyLocOrErr) + return ToAtFinallyLocOrErr.takeError(); + ExpectedStmt ToAtFinallyStmtOrErr = import(S->getFinallyBody()); + if (!ToAtFinallyStmtOrErr) + return ToAtFinallyStmtOrErr.takeError(); + return new (Importer.getToContext()) ObjCAtFinallyStmt(*ToAtFinallyLocOrErr, + *ToAtFinallyStmtOrErr); } -Stmt *ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - SourceLocation ToAtTryLoc = Importer.Import(S->getAtTryLoc()); - Stmt *ToAtTryStmt = Importer.Import(S->getTryBody()); - if (!ToAtTryStmt && S->getTryBody()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { + auto Imp = importSeq( + S->getAtTryLoc(), S->getTryBody(), S->getFinallyStmt()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToAtTryLoc; + Stmt *ToTryBody, *ToFinallyStmt; + std::tie(ToAtTryLoc, ToTryBody, ToFinallyStmt) = *Imp; + 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; + if (ExpectedStmt ToCatchStmtOrErr = import(FromCatchStmt)) + ToCatchStmts[CI] = *ToCatchStmtOrErr; else - return nullptr; + return ToCatchStmtOrErr.takeError(); } - Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyStmt()); - if (!ToAtFinallyStmt && S->getFinallyStmt()) - return nullptr; + return ObjCAtTryStmt::Create(Importer.getToContext(), - ToAtTryLoc, ToAtTryStmt, + ToAtTryLoc, ToTryBody, ToCatchStmts.begin(), ToCatchStmts.size(), - ToAtFinallyStmt); + ToFinallyStmt); } -Stmt *ASTNodeImporter::VisitObjCAtSynchronizedStmt +ExpectedStmt 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; + auto Imp = importSeq( + S->getAtSynchronizedLoc(), S->getSynchExpr(), S->getSynchBody()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToAtSynchronizedLoc; + Expr *ToSynchExpr; + Stmt *ToSynchBody; + std::tie(ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody) = *Imp; + 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); +ExpectedStmt ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { + ExpectedSLoc ToThrowLocOrErr = import(S->getThrowLoc()); + if (!ToThrowLocOrErr) + return ToThrowLocOrErr.takeError(); + ExpectedExpr ToThrowExprOrErr = import(S->getThrowExpr()); + if (!ToThrowExprOrErr) + return ToThrowExprOrErr.takeError(); + return new (Importer.getToContext()) ObjCAtThrowStmt( + *ToThrowLocOrErr, *ToThrowExprOrErr); } -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); +ExpectedStmt ASTNodeImporter::VisitObjCAutoreleasePoolStmt( + ObjCAutoreleasePoolStmt *S) { + ExpectedSLoc ToAtLocOrErr = import(S->getAtLoc()); + if (!ToAtLocOrErr) + return ToAtLocOrErr.takeError(); + ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt()); + if (!ToSubStmtOrErr) + return ToSubStmtOrErr.takeError(); + return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(*ToAtLocOrErr, + *ToSubStmtOrErr); } //---------------------------------------------------------------------------- // Import Expressions //---------------------------------------------------------------------------- -Expr *ASTNodeImporter::VisitExpr(Expr *E) { +ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node) << E->getStmtClassName(); - return nullptr; + return make_error<ImportError>(ImportError::UnsupportedConstruct); } -Expr *ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - Expr *SubExpr = Importer.Import(E->getSubExpr()); - if (!SubExpr && E->getSubExpr()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { + auto Imp = importSeq( + E->getBuiltinLoc(), E->getSubExpr(), E->getWrittenTypeInfo(), + E->getRParenLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); - TypeSourceInfo *TInfo = Importer.Import(E->getWrittenTypeInfo()); - if (!TInfo) - return nullptr; + SourceLocation ToBuiltinLoc, ToRParenLoc; + Expr *ToSubExpr; + TypeSourceInfo *ToWrittenTypeInfo; + QualType ToType; + std::tie(ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType) = + *Imp; return new (Importer.getToContext()) VAArgExpr( - Importer.Import(E->getBuiltinLoc()), SubExpr, TInfo, - Importer.Import(E->getRParenLoc()), T, E->isMicrosoftABI()); + ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType, + E->isMicrosoftABI()); } -Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - return new (Importer.getToContext()) - GNUNullExpr(T, Importer.Import(E->getBeginLoc())); +ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { + ExpectedType TypeOrErr = import(E->getType()); + if (!TypeOrErr) + return TypeOrErr.takeError(); + + ExpectedSLoc BeginLocOrErr = import(E->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + + return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr); } -Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { + auto Imp = importSeq( + E->getBeginLoc(), E->getType(), E->getFunctionName()); + if (!Imp) + return Imp.takeError(); - auto *SL = cast_or_null<StringLiteral>(Importer.Import(E->getFunctionName())); - if (!SL && E->getFunctionName()) - return nullptr; + SourceLocation ToBeginLoc; + QualType ToType; + StringLiteral *ToFunctionName; + std::tie(ToBeginLoc, ToType, ToFunctionName) = *Imp; - return new (Importer.getToContext()) PredefinedExpr( - Importer.Import(E->getBeginLoc()), T, E->getIdentType(), SL); + return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType, + E->getIdentKind(), ToFunctionName); } -Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { - auto *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl())); - if (!ToD) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { + auto Imp = importSeq( + E->getQualifierLoc(), E->getTemplateKeywordLoc(), E->getDecl(), + E->getLocation(), E->getType()); + if (!Imp) + return Imp.takeError(); + + NestedNameSpecifierLoc ToQualifierLoc; + SourceLocation ToTemplateKeywordLoc, ToLocation; + ValueDecl *ToDecl; + QualType ToType; + std::tie(ToQualifierLoc, ToTemplateKeywordLoc, ToDecl, ToLocation, ToType) = + *Imp; - NamedDecl *FoundD = nullptr; + NamedDecl *ToFoundD = nullptr; if (E->getDecl() != E->getFoundDecl()) { - FoundD = cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl())); - if (!FoundD) - return nullptr; + auto FoundDOrErr = import(E->getFoundDecl()); + if (!FoundDOrErr) + return FoundDOrErr.takeError(); + ToFoundD = *FoundDOrErr; } - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - TemplateArgumentListInfo ToTAInfo; - TemplateArgumentListInfo *ResInfo = nullptr; + TemplateArgumentListInfo *ToResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) - return nullptr; - ResInfo = &ToTAInfo; + if (Error Err = + ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + return std::move(Err); + ToResInfo = &ToTAInfo; } - DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), - Importer.Import(E->getQualifierLoc()), - Importer.Import(E->getTemplateKeywordLoc()), - ToD, - E->refersToEnclosingVariableOrCapture(), - Importer.Import(E->getLocation()), - T, E->getValueKind(), - FoundD, ResInfo); + auto *ToE = DeclRefExpr::Create( + Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl, + E->refersToEnclosingVariableOrCapture(), ToLocation, ToType, + E->getValueKind(), ToFoundD, ToResInfo); if (E->hadMultipleCandidates()) - DRE->setHadMultipleCandidates(true); - return DRE; -} - -Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - return new (Importer.getToContext()) ImplicitValueInitExpr(T); + ToE->setHadMultipleCandidates(true); + return ToE; } -ASTNodeImporter::Designator -ASTNodeImporter::ImportDesignator(const Designator &D) { - if (D.isFieldDesignator()) { - IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName()); - // Caller checks for import error - return Designator(ToFieldName, Importer.Import(D.getDotLoc()), - Importer.Import(D.getFieldLoc())); - } - if (D.isArrayDesignator()) - return Designator(D.getFirstExprIndex(), - Importer.Import(D.getLBracketLoc()), - Importer.Import(D.getRBracketLoc())); +ExpectedStmt ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { + ExpectedType TypeOrErr = import(E->getType()); + if (!TypeOrErr) + return TypeOrErr.takeError(); - assert(D.isArrayRangeDesignator()); - return Designator(D.getFirstExprIndex(), - Importer.Import(D.getLBracketLoc()), - Importer.Import(D.getEllipsisLoc()), - Importer.Import(D.getRBracketLoc())); + return new (Importer.getToContext()) ImplicitValueInitExpr(*TypeOrErr); } +ExpectedStmt ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *E) { + ExpectedExpr ToInitOrErr = import(E->getInit()); + if (!ToInitOrErr) + return ToInitOrErr.takeError(); -Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) { - auto *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit())); - if (!Init) - return nullptr; + ExpectedSLoc ToEqualOrColonLocOrErr = import(E->getEqualOrColonLoc()); + if (!ToEqualOrColonLocOrErr) + return ToEqualOrColonLocOrErr.takeError(); - SmallVector<Expr *, 4> IndexExprs(DIE->getNumSubExprs() - 1); + SmallVector<Expr *, 4> ToIndexExprs(E->getNumSubExprs() - 1); // List elements from the second, the first is Init itself - for (unsigned I = 1, E = DIE->getNumSubExprs(); I < E; I++) { - if (auto *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I)))) - IndexExprs[I - 1] = Arg; + for (unsigned I = 1, N = E->getNumSubExprs(); I < N; I++) { + if (ExpectedExpr ToArgOrErr = import(E->getSubExpr(I))) + ToIndexExprs[I - 1] = *ToArgOrErr; else - return nullptr; + return ToArgOrErr.takeError(); } - SmallVector<Designator, 4> Designators(DIE->size()); - llvm::transform(DIE->designators(), Designators.begin(), - [this](const Designator &D) -> Designator { - return ImportDesignator(D); - }); - - for (const auto &D : DIE->designators()) - if (D.isFieldDesignator() && !D.getFieldName()) - return nullptr; + SmallVector<Designator, 4> ToDesignators(E->size()); + if (Error Err = ImportContainerChecked(E->designators(), ToDesignators)) + return std::move(Err); return DesignatedInitExpr::Create( - Importer.getToContext(), Designators, - IndexExprs, Importer.Import(DIE->getEqualOrColonLoc()), - DIE->usesGNUSyntax(), Init); + Importer.getToContext(), ToDesignators, + ToIndexExprs, *ToEqualOrColonLocOrErr, + E->usesGNUSyntax(), *ToInitOrErr); } -Expr *ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt +ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - return new (Importer.getToContext()) - CXXNullPtrLiteralExpr(T, Importer.Import(E->getLocation())); + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); + + return new (Importer.getToContext()) CXXNullPtrLiteralExpr( + *ToTypeOrErr, *ToLocationOrErr); } -Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - return IntegerLiteral::Create(Importer.getToContext(), - E->getValue(), T, - Importer.Import(E->getLocation())); + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); + + return IntegerLiteral::Create( + Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr); } -Expr *ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - return FloatingLiteral::Create(Importer.getToContext(), - E->getValue(), E->isExact(), T, - Importer.Import(E->getLocation())); +ExpectedStmt ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); + + return FloatingLiteral::Create( + Importer.getToContext(), E->getValue(), E->isExact(), + *ToTypeOrErr, *ToLocationOrErr); } -Expr *ASTNodeImporter::VisitImaginaryLiteral(ImaginaryLiteral *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitImaginaryLiteral(ImaginaryLiteral *E) { + auto ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - Expr *SubE = Importer.Import(E->getSubExpr()); - if (!SubE) - return nullptr; + ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); + if (!ToSubExprOrErr) + return ToSubExprOrErr.takeError(); - return new (Importer.getToContext()) ImaginaryLiteral(SubE, T); + return new (Importer.getToContext()) ImaginaryLiteral( + *ToSubExprOrErr, *ToTypeOrErr); } -Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - return new (Importer.getToContext()) CharacterLiteral(E->getValue(), - E->getKind(), T, - Importer.Import(E->getLocation())); + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); + + return new (Importer.getToContext()) CharacterLiteral( + E->getValue(), E->getKind(), *ToTypeOrErr, *ToLocationOrErr); } -Expr *ASTNodeImporter::VisitStringLiteral(StringLiteral *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitStringLiteral(StringLiteral *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - SmallVector<SourceLocation, 4> Locations(E->getNumConcatenated()); - ImportArray(E->tokloc_begin(), E->tokloc_end(), Locations.begin()); + SmallVector<SourceLocation, 4> ToLocations(E->getNumConcatenated()); + if (Error Err = ImportArrayChecked( + E->tokloc_begin(), E->tokloc_end(), ToLocations.begin())) + return std::move(Err); - return StringLiteral::Create(Importer.getToContext(), E->getBytes(), - E->getKind(), E->isPascal(), T, - Locations.data(), Locations.size()); + return StringLiteral::Create( + Importer.getToContext(), E->getBytes(), E->getKind(), E->isPascal(), + *ToTypeOrErr, ToLocations.data(), ToLocations.size()); } -Expr *ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - TypeSourceInfo *TInfo = Importer.Import(E->getTypeSourceInfo()); - if (!TInfo) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + auto Imp = importSeq( + E->getLParenLoc(), E->getTypeSourceInfo(), E->getType(), + E->getInitializer()); + if (!Imp) + return Imp.takeError(); - Expr *Init = Importer.Import(E->getInitializer()); - if (!Init) - return nullptr; + SourceLocation ToLParenLoc; + TypeSourceInfo *ToTypeSourceInfo; + QualType ToType; + Expr *ToInitializer; + std::tie(ToLParenLoc, ToTypeSourceInfo, ToType, ToInitializer) = *Imp; return new (Importer.getToContext()) CompoundLiteralExpr( - Importer.Import(E->getLParenLoc()), TInfo, T, E->getValueKind(), - Init, E->isFileScope()); + ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(), + ToInitializer, E->isFileScope()); } -Expr *ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) { + auto Imp = importSeq( + E->getBuiltinLoc(), E->getType(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); - SmallVector<Expr *, 6> Exprs(E->getNumSubExprs()); - if (ImportArrayChecked( - E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(), - Exprs.begin())) - return nullptr; + SourceLocation ToBuiltinLoc, ToRParenLoc; + QualType ToType; + std::tie(ToBuiltinLoc, ToType, ToRParenLoc) = *Imp; + + SmallVector<Expr *, 6> ToExprs(E->getNumSubExprs()); + if (Error Err = ImportArrayChecked( + E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(), + ToExprs.begin())) + return std::move(Err); return new (Importer.getToContext()) AtomicExpr( - Importer.Import(E->getBuiltinLoc()), Exprs, T, E->getOp(), - Importer.Import(E->getRParenLoc())); + ToBuiltinLoc, ToExprs, ToType, E->getOp(), ToRParenLoc); } -Expr *ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { + auto Imp = importSeq( + E->getAmpAmpLoc(), E->getLabelLoc(), E->getLabel(), E->getType()); + if (!Imp) + return Imp.takeError(); - auto *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel())); - if (!ToLabel) - return nullptr; + SourceLocation ToAmpAmpLoc, ToLabelLoc; + LabelDecl *ToLabel; + QualType ToType; + std::tie(ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType) = *Imp; return new (Importer.getToContext()) AddrLabelExpr( - Importer.Import(E->getAmpAmpLoc()), Importer.Import(E->getLabelLoc()), - ToLabel, T); + ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType); } -Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { - Expr *SubExpr = Importer.Import(E->getSubExpr()); - if (!SubExpr) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { + auto Imp = importSeq(E->getSubExpr()); + if (!Imp) + return Imp.takeError(); + + Expr *ToSubExpr; + std::tie(ToSubExpr) = *Imp; + + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr); +} + +ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { + auto Imp = importSeq(E->getLParen(), E->getRParen(), E->getSubExpr()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToLParen, ToRParen; + Expr *ToSubExpr; + std::tie(ToLParen, ToRParen, ToSubExpr) = *Imp; return new (Importer.getToContext()) - ParenExpr(Importer.Import(E->getLParen()), - Importer.Import(E->getRParen()), - SubExpr); + ParenExpr(ToLParen, ToRParen, ToSubExpr); } -Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { - SmallVector<Expr *, 4> Exprs(E->getNumExprs()); - if (ImportContainerChecked(E->exprs(), Exprs)) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { + SmallVector<Expr *, 4> ToExprs(E->getNumExprs()); + if (Error Err = ImportContainerChecked(E->exprs(), ToExprs)) + return std::move(Err); + + ExpectedSLoc ToLParenLocOrErr = import(E->getLParenLoc()); + if (!ToLParenLocOrErr) + return ToLParenLocOrErr.takeError(); - return new (Importer.getToContext()) ParenListExpr( - Importer.getToContext(), Importer.Import(E->getLParenLoc()), - Exprs, Importer.Import(E->getLParenLoc())); + ExpectedSLoc ToRParenLocOrErr = import(E->getRParenLoc()); + if (!ToRParenLocOrErr) + return ToRParenLocOrErr.takeError(); + + return ParenListExpr::Create(Importer.getToContext(), *ToLParenLocOrErr, + ToExprs, *ToRParenLocOrErr); } -Expr *ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { + auto Imp = importSeq( + E->getSubStmt(), E->getType(), E->getLParenLoc(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); - auto *ToSubStmt = cast_or_null<CompoundStmt>( - Importer.Import(E->getSubStmt())); - if (!ToSubStmt && E->getSubStmt()) - return nullptr; + CompoundStmt *ToSubStmt; + QualType ToType; + SourceLocation ToLParenLoc, ToRParenLoc; + std::tie(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc) = *Imp; - return new (Importer.getToContext()) StmtExpr(ToSubStmt, T, - Importer.Import(E->getLParenLoc()), Importer.Import(E->getRParenLoc())); + return new (Importer.getToContext()) StmtExpr( + ToSubStmt, ToType, ToLParenLoc, ToRParenLoc); } -Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { + auto Imp = importSeq( + E->getSubExpr(), E->getType(), E->getOperatorLoc()); + if (!Imp) + return Imp.takeError(); - Expr *SubExpr = Importer.Import(E->getSubExpr()); - if (!SubExpr) - return nullptr; + Expr *ToSubExpr; + QualType ToType; + SourceLocation ToOperatorLoc; + std::tie(ToSubExpr, ToType, ToOperatorLoc) = *Imp; return new (Importer.getToContext()) UnaryOperator( - SubExpr, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(), - Importer.Import(E->getOperatorLoc()), E->canOverflow()); + ToSubExpr, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(), + ToOperatorLoc, E->canOverflow()); } -Expr * +ExpectedStmt ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { - QualType ResultType = Importer.Import(E->getType()); + auto Imp = importSeq(E->getType(), E->getOperatorLoc(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + SourceLocation ToOperatorLoc, ToRParenLoc; + std::tie(ToType, ToOperatorLoc, ToRParenLoc) = *Imp; if (E->isArgumentType()) { - TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo()); - if (!TInfo) - return nullptr; + Expected<TypeSourceInfo *> ToArgumentTypeInfoOrErr = + import(E->getArgumentTypeInfo()); + if (!ToArgumentTypeInfoOrErr) + return ToArgumentTypeInfoOrErr.takeError(); - return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(), - TInfo, ResultType, - Importer.Import(E->getOperatorLoc()), - Importer.Import(E->getRParenLoc())); + return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr( + E->getKind(), *ToArgumentTypeInfoOrErr, ToType, ToOperatorLoc, + ToRParenLoc); } - Expr *SubExpr = Importer.Import(E->getArgumentExpr()); - if (!SubExpr) - return nullptr; + ExpectedExpr ToArgumentExprOrErr = import(E->getArgumentExpr()); + if (!ToArgumentExprOrErr) + return ToArgumentExprOrErr.takeError(); - return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(), - SubExpr, ResultType, - Importer.Import(E->getOperatorLoc()), - Importer.Import(E->getRParenLoc())); + return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr( + E->getKind(), *ToArgumentExprOrErr, ToType, ToOperatorLoc, ToRParenLoc); } -Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - Expr *LHS = Importer.Import(E->getLHS()); - if (!LHS) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { + auto Imp = importSeq( + E->getLHS(), E->getRHS(), E->getType(), E->getOperatorLoc()); + if (!Imp) + return Imp.takeError(); - Expr *RHS = Importer.Import(E->getRHS()); - if (!RHS) - return nullptr; + Expr *ToLHS, *ToRHS; + QualType ToType; + SourceLocation ToOperatorLoc; + std::tie(ToLHS, ToRHS, ToType, ToOperatorLoc) = *Imp; - return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(), - T, E->getValueKind(), - E->getObjectKind(), - Importer.Import(E->getOperatorLoc()), - E->getFPFeatures()); + return new (Importer.getToContext()) BinaryOperator( + ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), + E->getObjectKind(), ToOperatorLoc, E->getFPFeatures()); } -Expr *ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { + auto Imp = importSeq( + E->getCond(), E->getQuestionLoc(), E->getLHS(), E->getColonLoc(), + E->getRHS(), E->getType()); + if (!Imp) + return Imp.takeError(); - Expr *ToLHS = Importer.Import(E->getLHS()); - if (!ToLHS) - return nullptr; - - Expr *ToRHS = Importer.Import(E->getRHS()); - if (!ToRHS) - return nullptr; - - Expr *ToCond = Importer.Import(E->getCond()); - if (!ToCond) - return nullptr; + Expr *ToCond, *ToLHS, *ToRHS; + SourceLocation ToQuestionLoc, ToColonLoc; + QualType ToType; + std::tie(ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType) = *Imp; return new (Importer.getToContext()) ConditionalOperator( - ToCond, Importer.Import(E->getQuestionLoc()), - ToLHS, Importer.Import(E->getColonLoc()), - ToRHS, T, E->getValueKind(), E->getObjectKind()); + ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType, + E->getValueKind(), E->getObjectKind()); } -Expr *ASTNodeImporter::VisitBinaryConditionalOperator( +ExpectedStmt ASTNodeImporter::VisitBinaryConditionalOperator( BinaryConditionalOperator *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - Expr *Common = Importer.Import(E->getCommon()); - if (!Common) - return nullptr; - - Expr *Cond = Importer.Import(E->getCond()); - if (!Cond) - return nullptr; - - auto *OpaqueValue = cast_or_null<OpaqueValueExpr>( - Importer.Import(E->getOpaqueValue())); - if (!OpaqueValue) - return nullptr; - - Expr *TrueExpr = Importer.Import(E->getTrueExpr()); - if (!TrueExpr) - return nullptr; - - Expr *FalseExpr = Importer.Import(E->getFalseExpr()); - if (!FalseExpr) - return nullptr; + auto Imp = importSeq( + E->getCommon(), E->getOpaqueValue(), E->getCond(), E->getTrueExpr(), + E->getFalseExpr(), E->getQuestionLoc(), E->getColonLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + Expr *ToCommon, *ToCond, *ToTrueExpr, *ToFalseExpr; + OpaqueValueExpr *ToOpaqueValue; + SourceLocation ToQuestionLoc, ToColonLoc; + QualType ToType; + std::tie( + ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr, ToQuestionLoc, + ToColonLoc, ToType) = *Imp; return new (Importer.getToContext()) BinaryConditionalOperator( - Common, OpaqueValue, Cond, TrueExpr, FalseExpr, - Importer.Import(E->getQuestionLoc()), Importer.Import(E->getColonLoc()), - T, E->getValueKind(), E->getObjectKind()); -} - -Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo()); - if (!ToQueried) - return nullptr; - - Expr *Dim = Importer.Import(E->getDimensionExpression()); - if (!Dim && E->getDimensionExpression()) - return nullptr; + ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr, + ToQuestionLoc, ToColonLoc, ToType, E->getValueKind(), + E->getObjectKind()); +} + +ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + auto Imp = importSeq( + E->getBeginLoc(), E->getQueriedTypeSourceInfo(), + E->getDimensionExpression(), E->getEndLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToBeginLoc, ToEndLoc; + TypeSourceInfo *ToQueriedTypeSourceInfo; + Expr *ToDimensionExpression; + QualType ToType; + std::tie( + ToBeginLoc, ToQueriedTypeSourceInfo, ToDimensionExpression, ToEndLoc, + ToType) = *Imp; return new (Importer.getToContext()) ArrayTypeTraitExpr( - Importer.Import(E->getBeginLoc()), E->getTrait(), ToQueried, - E->getValue(), Dim, Importer.Import(E->getEndLoc()), T); + ToBeginLoc, E->getTrait(), ToQueriedTypeSourceInfo, E->getValue(), + ToDimensionExpression, ToEndLoc, ToType); } -Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { + auto Imp = importSeq( + E->getBeginLoc(), E->getQueriedExpression(), E->getEndLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); - Expr *ToQueried = Importer.Import(E->getQueriedExpression()); - if (!ToQueried) - return nullptr; + SourceLocation ToBeginLoc, ToEndLoc; + Expr *ToQueriedExpression; + QualType ToType; + std::tie(ToBeginLoc, ToQueriedExpression, ToEndLoc, ToType) = *Imp; return new (Importer.getToContext()) ExpressionTraitExpr( - Importer.Import(E->getBeginLoc()), E->getTrait(), ToQueried, - E->getValue(), Importer.Import(E->getEndLoc()), T); + ToBeginLoc, E->getTrait(), ToQueriedExpression, E->getValue(), + ToEndLoc, ToType); } -Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { + auto Imp = importSeq( + E->getLocation(), E->getType(), E->getSourceExpr()); + if (!Imp) + return Imp.takeError(); - Expr *SourceExpr = Importer.Import(E->getSourceExpr()); - if (!SourceExpr && E->getSourceExpr()) - return nullptr; + SourceLocation ToLocation; + QualType ToType; + Expr *ToSourceExpr; + std::tie(ToLocation, ToType, ToSourceExpr) = *Imp; return new (Importer.getToContext()) OpaqueValueExpr( - Importer.Import(E->getLocation()), T, E->getValueKind(), - E->getObjectKind(), SourceExpr); + ToLocation, ToType, E->getValueKind(), E->getObjectKind(), ToSourceExpr); } -Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - Expr *ToLHS = Importer.Import(E->getLHS()); - if (!ToLHS) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + auto Imp = importSeq( + E->getLHS(), E->getRHS(), E->getType(), E->getRBracketLoc()); + if (!Imp) + return Imp.takeError(); - Expr *ToRHS = Importer.Import(E->getRHS()); - if (!ToRHS) - return nullptr; + Expr *ToLHS, *ToRHS; + SourceLocation ToRBracketLoc; + QualType ToType; + std::tie(ToLHS, ToRHS, ToType, ToRBracketLoc) = *Imp; return new (Importer.getToContext()) ArraySubscriptExpr( - ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(), - Importer.Import(E->getRBracketLoc())); + ToLHS, ToRHS, ToType, E->getValueKind(), E->getObjectKind(), + ToRBracketLoc); } -Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - QualType CompLHSType = Importer.Import(E->getComputationLHSType()); - if (CompLHSType.isNull()) - return nullptr; - - QualType CompResultType = Importer.Import(E->getComputationResultType()); - if (CompResultType.isNull()) - return nullptr; +ExpectedStmt +ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { + auto Imp = importSeq( + E->getLHS(), E->getRHS(), E->getType(), E->getComputationLHSType(), + E->getComputationResultType(), E->getOperatorLoc()); + if (!Imp) + return Imp.takeError(); - Expr *LHS = Importer.Import(E->getLHS()); - if (!LHS) - return nullptr; - - Expr *RHS = Importer.Import(E->getRHS()); - if (!RHS) - return nullptr; + Expr *ToLHS, *ToRHS; + QualType ToType, ToComputationLHSType, ToComputationResultType; + SourceLocation ToOperatorLoc; + std::tie(ToLHS, ToRHS, ToType, ToComputationLHSType, ToComputationResultType, + ToOperatorLoc) = *Imp; - return new (Importer.getToContext()) - CompoundAssignOperator(LHS, RHS, E->getOpcode(), - T, E->getValueKind(), - E->getObjectKind(), - CompLHSType, CompResultType, - Importer.Import(E->getOperatorLoc()), - E->getFPFeatures()); + return new (Importer.getToContext()) CompoundAssignOperator( + ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), + E->getObjectKind(), ToComputationLHSType, ToComputationResultType, + ToOperatorLoc, E->getFPFeatures()); } -bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) { +Expected<CXXCastPath> +ASTNodeImporter::ImportCastPath(CastExpr *CE) { + CXXCastPath Path; for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) { - if (CXXBaseSpecifier *Spec = Importer.Import(*I)) - Path.push_back(Spec); + if (auto SpecOrErr = import(*I)) + Path.push_back(*SpecOrErr); else - return true; + return SpecOrErr.takeError(); } - return false; + return Path; } -Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - Expr *SubExpr = Importer.Import(E->getSubExpr()); - if (!SubExpr) - return nullptr; + ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); + if (!ToSubExprOrErr) + return ToSubExprOrErr.takeError(); - CXXCastPath BasePath; - if (ImportCastPath(E, BasePath)) - return nullptr; + Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E); + if (!ToBasePathOrErr) + return ToBasePathOrErr.takeError(); - return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(), - SubExpr, &BasePath, E->getValueKind()); + return ImplicitCastExpr::Create( + Importer.getToContext(), *ToTypeOrErr, E->getCastKind(), *ToSubExprOrErr, + &(*ToBasePathOrErr), E->getValueKind()); } -Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - Expr *SubExpr = Importer.Import(E->getSubExpr()); - if (!SubExpr) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { + auto Imp1 = importSeq( + E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten()); + if (!Imp1) + return Imp1.takeError(); - TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten()); - if (!TInfo && E->getTypeInfoAsWritten()) - return nullptr; + QualType ToType; + Expr *ToSubExpr; + TypeSourceInfo *ToTypeInfoAsWritten; + std::tie(ToType, ToSubExpr, ToTypeInfoAsWritten) = *Imp1; - CXXCastPath BasePath; - if (ImportCastPath(E, BasePath)) - return nullptr; + Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E); + if (!ToBasePathOrErr) + return ToBasePathOrErr.takeError(); + CXXCastPath *ToBasePath = &(*ToBasePathOrErr); switch (E->getStmtClass()) { case Stmt::CStyleCastExprClass: { auto *CCE = cast<CStyleCastExpr>(E); - return CStyleCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), E->getCastKind(), - SubExpr, &BasePath, TInfo, - Importer.Import(CCE->getLParenLoc()), - Importer.Import(CCE->getRParenLoc())); + ExpectedSLoc ToLParenLocOrErr = import(CCE->getLParenLoc()); + if (!ToLParenLocOrErr) + return ToLParenLocOrErr.takeError(); + ExpectedSLoc ToRParenLocOrErr = import(CCE->getRParenLoc()); + if (!ToRParenLocOrErr) + return ToRParenLocOrErr.takeError(); + return CStyleCastExpr::Create( + Importer.getToContext(), ToType, E->getValueKind(), E->getCastKind(), + ToSubExpr, ToBasePath, ToTypeInfoAsWritten, *ToLParenLocOrErr, + *ToRParenLocOrErr); } case Stmt::CXXFunctionalCastExprClass: { auto *FCE = cast<CXXFunctionalCastExpr>(E); - return CXXFunctionalCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), TInfo, - E->getCastKind(), SubExpr, &BasePath, - Importer.Import(FCE->getLParenLoc()), - Importer.Import(FCE->getRParenLoc())); + ExpectedSLoc ToLParenLocOrErr = import(FCE->getLParenLoc()); + if (!ToLParenLocOrErr) + return ToLParenLocOrErr.takeError(); + ExpectedSLoc ToRParenLocOrErr = import(FCE->getRParenLoc()); + if (!ToRParenLocOrErr) + return ToRParenLocOrErr.takeError(); + return CXXFunctionalCastExpr::Create( + Importer.getToContext(), ToType, E->getValueKind(), ToTypeInfoAsWritten, + E->getCastKind(), ToSubExpr, ToBasePath, *ToLParenLocOrErr, + *ToRParenLocOrErr); } case Stmt::ObjCBridgedCastExprClass: { - auto *OCE = cast<ObjCBridgedCastExpr>(E); - return new (Importer.getToContext()) ObjCBridgedCastExpr( - Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(), - E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()), - TInfo, SubExpr); + auto *OCE = cast<ObjCBridgedCastExpr>(E); + ExpectedSLoc ToLParenLocOrErr = import(OCE->getLParenLoc()); + if (!ToLParenLocOrErr) + return ToLParenLocOrErr.takeError(); + ExpectedSLoc ToBridgeKeywordLocOrErr = import(OCE->getBridgeKeywordLoc()); + if (!ToBridgeKeywordLocOrErr) + return ToBridgeKeywordLocOrErr.takeError(); + return new (Importer.getToContext()) ObjCBridgedCastExpr( + *ToLParenLocOrErr, OCE->getBridgeKind(), E->getCastKind(), + *ToBridgeKeywordLocOrErr, ToTypeInfoAsWritten, ToSubExpr); } default: llvm_unreachable("Cast expression of unsupported type!"); - return nullptr; + return make_error<ImportError>(ImportError::UnsupportedConstruct); } } -Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) { - QualType T = Importer.Import(OE->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) { + SmallVector<OffsetOfNode, 4> ToNodes; + for (int I = 0, N = E->getNumComponents(); I < N; ++I) { + const OffsetOfNode &FromNode = E->getComponent(I); - SmallVector<OffsetOfNode, 4> Nodes; - for (int I = 0, E = OE->getNumComponents(); I < E; ++I) { - const OffsetOfNode &Node = OE->getComponent(I); + SourceLocation ToBeginLoc, ToEndLoc; + if (FromNode.getKind() != OffsetOfNode::Base) { + auto Imp = importSeq(FromNode.getBeginLoc(), FromNode.getEndLoc()); + if (!Imp) + return Imp.takeError(); + std::tie(ToBeginLoc, ToEndLoc) = *Imp; + } - switch (Node.getKind()) { + switch (FromNode.getKind()) { case OffsetOfNode::Array: - Nodes.push_back(OffsetOfNode(Importer.Import(Node.getBeginLoc()), - Node.getArrayExprIndex(), - Importer.Import(Node.getEndLoc()))); + ToNodes.push_back( + OffsetOfNode(ToBeginLoc, FromNode.getArrayExprIndex(), ToEndLoc)); break; - case OffsetOfNode::Base: { - CXXBaseSpecifier *BS = Importer.Import(Node.getBase()); - if (!BS && Node.getBase()) - return nullptr; - Nodes.push_back(OffsetOfNode(BS)); + auto ToBSOrErr = import(FromNode.getBase()); + if (!ToBSOrErr) + return ToBSOrErr.takeError(); + ToNodes.push_back(OffsetOfNode(*ToBSOrErr)); break; } case OffsetOfNode::Field: { - auto *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField())); - if (!FD) - return nullptr; - Nodes.push_back(OffsetOfNode(Importer.Import(Node.getBeginLoc()), FD, - Importer.Import(Node.getEndLoc()))); + auto ToFieldOrErr = import(FromNode.getField()); + if (!ToFieldOrErr) + return ToFieldOrErr.takeError(); + ToNodes.push_back(OffsetOfNode(ToBeginLoc, *ToFieldOrErr, ToEndLoc)); break; } case OffsetOfNode::Identifier: { - IdentifierInfo *ToII = Importer.Import(Node.getFieldName()); - if (!ToII) - return nullptr; - Nodes.push_back(OffsetOfNode(Importer.Import(Node.getBeginLoc()), ToII, - Importer.Import(Node.getEndLoc()))); + IdentifierInfo *ToII = Importer.Import(FromNode.getFieldName()); + ToNodes.push_back(OffsetOfNode(ToBeginLoc, ToII, ToEndLoc)); break; } } } - SmallVector<Expr *, 4> Exprs(OE->getNumExpressions()); - for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) { - Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I)); - if (!ToIndexExpr) - return nullptr; - Exprs[I] = ToIndexExpr; + SmallVector<Expr *, 4> ToExprs(E->getNumExpressions()); + for (int I = 0, N = E->getNumExpressions(); I < N; ++I) { + ExpectedExpr ToIndexExprOrErr = import(E->getIndexExpr(I)); + if (!ToIndexExprOrErr) + return ToIndexExprOrErr.takeError(); + ToExprs[I] = *ToIndexExprOrErr; } - TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo()); - if (!TInfo && OE->getTypeSourceInfo()) - return nullptr; + auto Imp = importSeq( + E->getType(), E->getTypeSourceInfo(), E->getOperatorLoc(), + E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); - return OffsetOfExpr::Create(Importer.getToContext(), T, - Importer.Import(OE->getOperatorLoc()), - TInfo, Nodes, Exprs, - Importer.Import(OE->getRParenLoc())); + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToOperatorLoc, ToRParenLoc; + std::tie(ToType, ToTypeSourceInfo, ToOperatorLoc, ToRParenLoc) = *Imp; + + return OffsetOfExpr::Create( + Importer.getToContext(), ToType, ToOperatorLoc, ToTypeSourceInfo, ToNodes, + ToExprs, ToRParenLoc); } -Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { + auto Imp = importSeq( + E->getType(), E->getOperand(), E->getBeginLoc(), E->getEndLoc()); + if (!Imp) + return Imp.takeError(); - Expr *Operand = Importer.Import(E->getOperand()); - if (!Operand) - return nullptr; + QualType ToType; + Expr *ToOperand; + SourceLocation ToBeginLoc, ToEndLoc; + std::tie(ToType, ToOperand, ToBeginLoc, ToEndLoc) = *Imp; - CanThrowResult CanThrow; + CanThrowResult ToCanThrow; if (E->isValueDependent()) - CanThrow = CT_Dependent; + ToCanThrow = CT_Dependent; else - CanThrow = E->getValue() ? CT_Can : CT_Cannot; + ToCanThrow = E->getValue() ? CT_Can : CT_Cannot; - return new (Importer.getToContext()) - CXXNoexceptExpr(T, Operand, CanThrow, Importer.Import(E->getBeginLoc()), - Importer.Import(E->getEndLoc())); + return new (Importer.getToContext()) CXXNoexceptExpr( + ToType, ToOperand, ToCanThrow, ToBeginLoc, ToEndLoc); } -Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) { + auto Imp = importSeq(E->getSubExpr(), E->getType(), E->getThrowLoc()); + if (!Imp) + return Imp.takeError(); - Expr *SubExpr = Importer.Import(E->getSubExpr()); - if (!SubExpr && E->getSubExpr()) - return nullptr; + Expr *ToSubExpr; + QualType ToType; + SourceLocation ToThrowLoc; + std::tie(ToSubExpr, ToType, ToThrowLoc) = *Imp; return new (Importer.getToContext()) CXXThrowExpr( - SubExpr, T, Importer.Import(E->getThrowLoc()), - E->isThrownVariableInScope()); + ToSubExpr, ToType, ToThrowLoc, E->isThrownVariableInScope()); } -Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - auto *Param = cast_or_null<ParmVarDecl>(Importer.Import(E->getParam())); - if (!Param) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + ExpectedSLoc ToUsedLocOrErr = import(E->getUsedLocation()); + if (!ToUsedLocOrErr) + return ToUsedLocOrErr.takeError(); + + auto ToParamOrErr = import(E->getParam()); + if (!ToParamOrErr) + return ToParamOrErr.takeError(); return CXXDefaultArgExpr::Create( - Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param); + Importer.getToContext(), *ToUsedLocOrErr, *ToParamOrErr); } -Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt +ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { + auto Imp = importSeq( + E->getType(), E->getTypeSourceInfo(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); - TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo()); - if (!TypeInfo) - return nullptr; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToRParenLoc; + std::tie(ToType, ToTypeSourceInfo, ToRParenLoc) = *Imp; return new (Importer.getToContext()) CXXScalarValueInitExpr( - T, TypeInfo, Importer.Import(E->getRParenLoc())); + ToType, ToTypeSourceInfo, ToRParenLoc); } -Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - Expr *SubExpr = Importer.Import(E->getSubExpr()); - if (!SubExpr) - return nullptr; +ExpectedStmt +ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); + if (!ToSubExprOrErr) + return ToSubExprOrErr.takeError(); - auto *Dtor = cast_or_null<CXXDestructorDecl>( - Importer.Import(const_cast<CXXDestructorDecl *>( - E->getTemporary()->getDestructor()))); - if (!Dtor) - return nullptr; + auto ToDtorOrErr = import(E->getTemporary()->getDestructor()); + if (!ToDtorOrErr) + return ToDtorOrErr.takeError(); ASTContext &ToCtx = Importer.getToContext(); - CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor); - return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr); + CXXTemporary *Temp = CXXTemporary::Create(ToCtx, *ToDtorOrErr); + return CXXBindTemporaryExpr::Create(ToCtx, Temp, *ToSubExprOrErr); } -Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) { - QualType T = Importer.Import(CE->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt +ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { + auto Imp = importSeq( + E->getConstructor(), E->getType(), E->getTypeSourceInfo(), + E->getParenOrBraceRange()); + if (!Imp) + return Imp.takeError(); - TypeSourceInfo *TInfo = Importer.Import(CE->getTypeSourceInfo()); - if (!TInfo) - return nullptr; - - SmallVector<Expr *, 8> Args(CE->getNumArgs()); - if (ImportContainerChecked(CE->arguments(), Args)) - return nullptr; + CXXConstructorDecl *ToConstructor; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceRange ToParenOrBraceRange; + std::tie(ToConstructor, ToType, ToTypeSourceInfo, ToParenOrBraceRange) = *Imp; - auto *Ctor = cast_or_null<CXXConstructorDecl>( - Importer.Import(CE->getConstructor())); - if (!Ctor) - return nullptr; + SmallVector<Expr *, 8> ToArgs(E->getNumArgs()); + if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) + return std::move(Err); return new (Importer.getToContext()) CXXTemporaryObjectExpr( - Importer.getToContext(), Ctor, T, TInfo, Args, - Importer.Import(CE->getParenOrBraceRange()), CE->hadMultipleCandidates(), - CE->isListInitialization(), CE->isStdInitListInitialization(), - CE->requiresZeroInitialization()); + Importer.getToContext(), ToConstructor, ToType, ToTypeSourceInfo, ToArgs, + ToParenOrBraceRange, E->hadMultipleCandidates(), + E->isListInitialization(), E->isStdInitListInitialization(), + E->requiresZeroInitialization()); } -Expr * +ExpectedStmt ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - Expr *TempE = Importer.Import(E->GetTemporaryExpr()); - if (!TempE) - return nullptr; + auto Imp = importSeq( + E->getType(), E->GetTemporaryExpr(), E->getExtendingDecl()); + if (!Imp) + return Imp.takeError(); - auto *ExtendedBy = cast_or_null<ValueDecl>( - Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl()))); - if (!ExtendedBy && E->getExtendingDecl()) - return nullptr; + QualType ToType; + Expr *ToTemporaryExpr; + const ValueDecl *ToExtendingDecl; + std::tie(ToType, ToTemporaryExpr, ToExtendingDecl) = *Imp; auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( - T, TempE, E->isBoundToLvalueReference()); + ToType, ToTemporaryExpr, E->isBoundToLvalueReference()); // FIXME: Should ManglingNumber get numbers associated with 'to' context? - ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber()); + ToMTE->setExtendingDecl(ToExtendingDecl, E->getManglingNumber()); return ToMTE; } -Expr *ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) { + auto Imp = importSeq( + E->getType(), E->getPattern(), E->getEllipsisLoc()); + if (!Imp) + return Imp.takeError(); - Expr *Pattern = Importer.Import(E->getPattern()); - if (!Pattern) - return nullptr; + QualType ToType; + Expr *ToPattern; + SourceLocation ToEllipsisLoc; + std::tie(ToType, ToPattern, ToEllipsisLoc) = *Imp; return new (Importer.getToContext()) PackExpansionExpr( - T, Pattern, Importer.Import(E->getEllipsisLoc()), - E->getNumExpansions()); + ToType, ToPattern, ToEllipsisLoc, E->getNumExpansions()); } -Expr *ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { - auto *Pack = cast_or_null<NamedDecl>(Importer.Import(E->getPack())); - if (!Pack) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { + auto Imp = importSeq( + E->getOperatorLoc(), E->getPack(), E->getPackLoc(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); - Optional<unsigned> Length; + SourceLocation ToOperatorLoc, ToPackLoc, ToRParenLoc; + NamedDecl *ToPack; + std::tie(ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc) = *Imp; + Optional<unsigned> Length; if (!E->isValueDependent()) Length = E->getPackLength(); - SmallVector<TemplateArgument, 8> PartialArguments; + SmallVector<TemplateArgument, 8> ToPartialArguments; if (E->isPartiallySubstituted()) { - if (ImportTemplateArguments(E->getPartialArguments().data(), - E->getPartialArguments().size(), - PartialArguments)) - return nullptr; + if (Error Err = ImportTemplateArguments( + E->getPartialArguments().data(), + E->getPartialArguments().size(), + ToPartialArguments)) + return std::move(Err); } return SizeOfPackExpr::Create( - Importer.getToContext(), Importer.Import(E->getOperatorLoc()), Pack, - Importer.Import(E->getPackLoc()), Importer.Import(E->getRParenLoc()), - Length, PartialArguments); -} - -Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) { - QualType T = Importer.Import(CE->getType()); - if (T.isNull()) - return nullptr; - - SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs()); - if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs)) - return nullptr; - - auto *OperatorNewDecl = cast_or_null<FunctionDecl>( - Importer.Import(CE->getOperatorNew())); - if (!OperatorNewDecl && CE->getOperatorNew()) - return nullptr; - - auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>( - Importer.Import(CE->getOperatorDelete())); - if (!OperatorDeleteDecl && CE->getOperatorDelete()) - return nullptr; - - Expr *ToInit = Importer.Import(CE->getInitializer()); - if (!ToInit && CE->getInitializer()) - return nullptr; - - TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo()); - if (!TInfo) - return nullptr; - - Expr *ToArrSize = Importer.Import(CE->getArraySize()); - if (!ToArrSize && CE->getArraySize()) - return nullptr; + Importer.getToContext(), ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc, + Length, ToPartialArguments); +} + + +ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) { + auto Imp = importSeq( + E->getOperatorNew(), E->getOperatorDelete(), E->getTypeIdParens(), + E->getArraySize(), E->getInitializer(), E->getType(), + E->getAllocatedTypeSourceInfo(), E->getSourceRange(), + E->getDirectInitRange()); + if (!Imp) + return Imp.takeError(); + + FunctionDecl *ToOperatorNew, *ToOperatorDelete; + SourceRange ToTypeIdParens, ToSourceRange, ToDirectInitRange; + Expr *ToArraySize, *ToInitializer; + QualType ToType; + TypeSourceInfo *ToAllocatedTypeSourceInfo; + std::tie( + ToOperatorNew, ToOperatorDelete, ToTypeIdParens, ToArraySize, ToInitializer, + ToType, ToAllocatedTypeSourceInfo, ToSourceRange, ToDirectInitRange) = *Imp; + + SmallVector<Expr *, 4> ToPlacementArgs(E->getNumPlacementArgs()); + if (Error Err = + ImportContainerChecked(E->placement_arguments(), ToPlacementArgs)) + return std::move(Err); return new (Importer.getToContext()) CXXNewExpr( - Importer.getToContext(), - CE->isGlobalNew(), - OperatorNewDecl, OperatorDeleteDecl, - CE->passAlignment(), - CE->doesUsualArrayDeleteWantSize(), - PlacementArgs, - Importer.Import(CE->getTypeIdParens()), - ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo, - Importer.Import(CE->getSourceRange()), - Importer.Import(CE->getDirectInitRange())); -} - -Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; + Importer.getToContext(), E->isGlobalNew(), ToOperatorNew, + ToOperatorDelete, E->passAlignment(), E->doesUsualArrayDeleteWantSize(), + ToPlacementArgs, ToTypeIdParens, ToArraySize, E->getInitializationStyle(), + ToInitializer, ToType, ToAllocatedTypeSourceInfo, ToSourceRange, + ToDirectInitRange); +} - auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>( - Importer.Import(E->getOperatorDelete())); - if (!OperatorDeleteDecl && E->getOperatorDelete()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { + auto Imp = importSeq( + E->getType(), E->getOperatorDelete(), E->getArgument(), E->getBeginLoc()); + if (!Imp) + return Imp.takeError(); - Expr *ToArg = Importer.Import(E->getArgument()); - if (!ToArg && E->getArgument()) - return nullptr; + QualType ToType; + FunctionDecl *ToOperatorDelete; + Expr *ToArgument; + SourceLocation ToBeginLoc; + std::tie(ToType, ToOperatorDelete, ToArgument, ToBeginLoc) = *Imp; return new (Importer.getToContext()) CXXDeleteExpr( - T, E->isGlobalDelete(), E->isArrayForm(), E->isArrayFormAsWritten(), - E->doesUsualArrayDeleteWantSize(), OperatorDeleteDecl, ToArg, - Importer.Import(E->getBeginLoc())); + ToType, E->isGlobalDelete(), E->isArrayForm(), E->isArrayFormAsWritten(), + E->doesUsualArrayDeleteWantSize(), ToOperatorDelete, ToArgument, + ToBeginLoc); } -Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { + auto Imp = importSeq( + E->getType(), E->getLocation(), E->getConstructor(), + E->getParenOrBraceRange()); + if (!Imp) + return Imp.takeError(); - auto *ToCCD = - dyn_cast_or_null<CXXConstructorDecl>(Importer.Import(E->getConstructor())); - if (!ToCCD) - return nullptr; + QualType ToType; + SourceLocation ToLocation; + CXXConstructorDecl *ToConstructor; + SourceRange ToParenOrBraceRange; + std::tie(ToType, ToLocation, ToConstructor, ToParenOrBraceRange) = *Imp; SmallVector<Expr *, 6> ToArgs(E->getNumArgs()); - if (ImportContainerChecked(E->arguments(), ToArgs)) - return nullptr; + if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) + return std::move(Err); - 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())); + return CXXConstructExpr::Create( + Importer.getToContext(), ToType, ToLocation, ToConstructor, + E->isElidable(), ToArgs, E->hadMultipleCandidates(), + E->isListInitialization(), E->isStdInitListInitialization(), + E->requiresZeroInitialization(), E->getConstructionKind(), + ToParenOrBraceRange); } -Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) { - Expr *SubExpr = Importer.Import(EWC->getSubExpr()); - if (!SubExpr && EWC->getSubExpr()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *E) { + ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); + if (!ToSubExprOrErr) + return ToSubExprOrErr.takeError(); - SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects()); - for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++) - if (ExprWithCleanups::CleanupObject Obj = - cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I)))) - Objs[I] = Obj; - else - return nullptr; + SmallVector<ExprWithCleanups::CleanupObject, 8> ToObjects(E->getNumObjects()); + if (Error Err = ImportContainerChecked(E->getObjects(), ToObjects)) + return std::move(Err); - return ExprWithCleanups::Create(Importer.getToContext(), - SubExpr, EWC->cleanupsHaveSideEffects(), - Objs); + return ExprWithCleanups::Create( + Importer.getToContext(), *ToSubExprOrErr, E->cleanupsHaveSideEffects(), + ToObjects); } -Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { + auto Imp = importSeq( + E->getCallee(), E->getType(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); - Expr *ToFn = Importer.Import(E->getCallee()); - if (!ToFn) - return nullptr; + Expr *ToCallee; + QualType ToType; + SourceLocation ToRParenLoc; + std::tie(ToCallee, ToType, ToRParenLoc) = *Imp; SmallVector<Expr *, 4> ToArgs(E->getNumArgs()); - if (ImportContainerChecked(E->arguments(), ToArgs)) - return nullptr; + if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) + return std::move(Err); return new (Importer.getToContext()) CXXMemberCallExpr( - Importer.getToContext(), ToFn, ToArgs, T, E->getValueKind(), - Importer.Import(E->getRParenLoc())); -} - -Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - return new (Importer.getToContext()) - CXXThisExpr(Importer.Import(E->getLocation()), T, E->isImplicit()); -} - -Expr *ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - return new (Importer.getToContext()) - CXXBoolLiteralExpr(E->getValue(), T, Importer.Import(E->getLocation())); -} - - -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; - - auto *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl())); - if (!ToMember && E->getMemberDecl()) - return nullptr; - - auto *ToDecl = - dyn_cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())); - if (!ToDecl && E->getFoundDecl().getDecl()) - return nullptr; + Importer.getToContext(), ToCallee, ToArgs, ToType, E->getValueKind(), + ToRParenLoc); +} + +ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); + + return new (Importer.getToContext()) CXXThisExpr( + *ToLocationOrErr, *ToTypeOrErr, E->isImplicit()); +} + +ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); + + return new (Importer.getToContext()) CXXBoolLiteralExpr( + E->getValue(), *ToTypeOrErr, *ToLocationOrErr); +} + +ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { + auto Imp1 = importSeq( + E->getBase(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getTemplateKeywordLoc(), E->getMemberDecl(), E->getType()); + if (!Imp1) + return Imp1.takeError(); + + Expr *ToBase; + SourceLocation ToOperatorLoc, ToTemplateKeywordLoc; + NestedNameSpecifierLoc ToQualifierLoc; + ValueDecl *ToMemberDecl; + QualType ToType; + std::tie( + ToBase, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, + ToType) = *Imp1; + + auto Imp2 = importSeq( + E->getFoundDecl().getDecl(), E->getMemberNameInfo().getName(), + E->getMemberNameInfo().getLoc(), E->getLAngleLoc(), E->getRAngleLoc()); + if (!Imp2) + return Imp2.takeError(); + NamedDecl *ToDecl; + DeclarationName ToName; + SourceLocation ToLoc, ToLAngleLoc, ToRAngleLoc; + std::tie(ToDecl, ToName, ToLoc, ToLAngleLoc, ToRAngleLoc) = *Imp2; DeclAccessPair ToFoundDecl = DeclAccessPair::make(ToDecl, E->getFoundDecl().getAccess()); - DeclarationNameInfo ToMemberNameInfo( - Importer.Import(E->getMemberNameInfo().getName()), - Importer.Import(E->getMemberNameInfo().getLoc())); + DeclarationNameInfo ToMemberNameInfo(ToName, ToLoc); if (E->hasExplicitTemplateArgs()) { - return nullptr; // FIXME: handle template arguments + // FIXME: handle template arguments + return make_error<ImportError>(ImportError::UnsupportedConstruct); } - 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()); + return MemberExpr::Create( + Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc, + ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, ToFoundDecl, + ToMemberNameInfo, nullptr, ToType, E->getValueKind(), E->getObjectKind()); } -Expr *ASTNodeImporter::VisitCXXPseudoDestructorExpr( - CXXPseudoDestructorExpr *E) { - Expr *BaseE = Importer.Import(E->getBase()); - if (!BaseE) - return nullptr; +ExpectedStmt +ASTNodeImporter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { + auto Imp = importSeq( + E->getBase(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getScopeTypeInfo(), E->getColonColonLoc(), E->getTildeLoc()); + if (!Imp) + return Imp.takeError(); - TypeSourceInfo *ScopeInfo = Importer.Import(E->getScopeTypeInfo()); - if (!ScopeInfo && E->getScopeTypeInfo()) - return nullptr; + Expr *ToBase; + SourceLocation ToOperatorLoc, ToColonColonLoc, ToTildeLoc; + NestedNameSpecifierLoc ToQualifierLoc; + TypeSourceInfo *ToScopeTypeInfo; + std::tie( + ToBase, ToOperatorLoc, ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc, + ToTildeLoc) = *Imp; PseudoDestructorTypeStorage Storage; if (IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) { IdentifierInfo *ToII = Importer.Import(FromII); - if (!ToII) - return nullptr; - Storage = PseudoDestructorTypeStorage( - ToII, Importer.Import(E->getDestroyedTypeLoc())); + ExpectedSLoc ToDestroyedTypeLocOrErr = import(E->getDestroyedTypeLoc()); + if (!ToDestroyedTypeLocOrErr) + return ToDestroyedTypeLocOrErr.takeError(); + Storage = PseudoDestructorTypeStorage(ToII, *ToDestroyedTypeLocOrErr); } else { - TypeSourceInfo *TI = Importer.Import(E->getDestroyedTypeInfo()); - if (!TI) - return nullptr; - Storage = PseudoDestructorTypeStorage(TI); + if (auto ToTIOrErr = import(E->getDestroyedTypeInfo())) + Storage = PseudoDestructorTypeStorage(*ToTIOrErr); + else + return ToTIOrErr.takeError(); } return new (Importer.getToContext()) CXXPseudoDestructorExpr( - Importer.getToContext(), BaseE, E->isArrow(), - Importer.Import(E->getOperatorLoc()), - Importer.Import(E->getQualifierLoc()), - ScopeInfo, Importer.Import(E->getColonColonLoc()), - Importer.Import(E->getTildeLoc()), Storage); + Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc, + ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc, ToTildeLoc, Storage); } -Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr( +ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr( CXXDependentScopeMemberExpr *E) { - Expr *Base = nullptr; + auto Imp = importSeq( + E->getType(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getTemplateKeywordLoc(), E->getFirstQualifierFoundInScope()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + SourceLocation ToOperatorLoc, ToTemplateKeywordLoc; + NestedNameSpecifierLoc ToQualifierLoc; + NamedDecl *ToFirstQualifierFoundInScope; + std::tie( + ToType, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, + ToFirstQualifierFoundInScope) = *Imp; + + Expr *ToBase = nullptr; if (!E->isImplicitAccess()) { - Base = Importer.Import(E->getBase()); - if (!Base) - return nullptr; + if (ExpectedExpr ToBaseOrErr = import(E->getBase())) + ToBase = *ToBaseOrErr; + else + return ToBaseOrErr.takeError(); } - QualType BaseType = Importer.Import(E->getBaseType()); - if (BaseType.isNull()) - return nullptr; - TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), - E->template_arguments(), ToTAInfo)) - return nullptr; + if (Error Err = ImportTemplateArgumentListInfo( + E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(), + ToTAInfo)) + return std::move(Err); ResInfo = &ToTAInfo; } - DeclarationName Name = Importer.Import(E->getMember()); - if (!E->getMember().isEmpty() && Name.isEmpty()) - return nullptr; - - DeclarationNameInfo MemberNameInfo(Name, Importer.Import(E->getMemberLoc())); + auto ToMemberNameInfoOrErr = importSeq(E->getMember(), E->getMemberLoc()); + if (!ToMemberNameInfoOrErr) + return ToMemberNameInfoOrErr.takeError(); + DeclarationNameInfo ToMemberNameInfo( + std::get<0>(*ToMemberNameInfoOrErr), std::get<1>(*ToMemberNameInfoOrErr)); // Import additional name location/type info. - ImportDeclarationNameLoc(E->getMemberNameInfo(), MemberNameInfo); - auto ToFQ = Importer.Import(E->getFirstQualifierFoundInScope()); - if (!ToFQ && E->getFirstQualifierFoundInScope()) - return nullptr; + if (Error Err = ImportDeclarationNameLoc( + E->getMemberNameInfo(), ToMemberNameInfo)) + return std::move(Err); return CXXDependentScopeMemberExpr::Create( - Importer.getToContext(), Base, BaseType, E->isArrow(), - Importer.Import(E->getOperatorLoc()), - Importer.Import(E->getQualifierLoc()), - Importer.Import(E->getTemplateKeywordLoc()), - cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo); + Importer.getToContext(), ToBase, ToType, E->isArrow(), ToOperatorLoc, + ToQualifierLoc, ToTemplateKeywordLoc, ToFirstQualifierFoundInScope, + ToMemberNameInfo, ResInfo); } -Expr * +ExpectedStmt ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - DeclarationName Name = Importer.Import(E->getDeclName()); - if (!E->getDeclName().isEmpty() && Name.isEmpty()) - return nullptr; - - DeclarationNameInfo NameInfo(Name, Importer.Import(E->getExprLoc())); - ImportDeclarationNameLoc(E->getNameInfo(), NameInfo); - - TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()), - Importer.Import(E->getRAngleLoc())); + auto Imp = importSeq( + E->getQualifierLoc(), E->getTemplateKeywordLoc(), E->getDeclName(), + E->getExprLoc(), E->getLAngleLoc(), E->getRAngleLoc()); + if (!Imp) + return Imp.takeError(); + + NestedNameSpecifierLoc ToQualifierLoc; + SourceLocation ToTemplateKeywordLoc, ToExprLoc, ToLAngleLoc, ToRAngleLoc; + DeclarationName ToDeclName; + std::tie( + ToQualifierLoc, ToTemplateKeywordLoc, ToDeclName, ToExprLoc, + ToLAngleLoc, ToRAngleLoc) = *Imp; + + DeclarationNameInfo ToNameInfo(ToDeclName, ToExprLoc); + if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) + return std::move(Err); + + TemplateArgumentListInfo ToTAInfo(ToLAngleLoc, ToRAngleLoc); TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) - return nullptr; + if (Error Err = + ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + return std::move(Err); ResInfo = &ToTAInfo; } return DependentScopeDeclRefExpr::Create( - Importer.getToContext(), Importer.Import(E->getQualifierLoc()), - Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo); + Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, + ToNameInfo, ResInfo); } -Expr *ASTNodeImporter::VisitCXXUnresolvedConstructExpr( - CXXUnresolvedConstructExpr *CE) { - unsigned NumArgs = CE->arg_size(); +ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr( + CXXUnresolvedConstructExpr *E) { + auto Imp = importSeq( + E->getLParenLoc(), E->getRParenLoc(), E->getTypeSourceInfo()); + if (!Imp) + return Imp.takeError(); - SmallVector<Expr *, 8> ToArgs(NumArgs); - if (ImportArrayChecked(CE->arg_begin(), CE->arg_end(), ToArgs.begin())) - return nullptr; + SourceLocation ToLParenLoc, ToRParenLoc; + TypeSourceInfo *ToTypeSourceInfo; + std::tie(ToLParenLoc, ToRParenLoc, ToTypeSourceInfo) = *Imp; + + SmallVector<Expr *, 8> ToArgs(E->arg_size()); + if (Error Err = + ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) + return std::move(Err); return CXXUnresolvedConstructExpr::Create( - Importer.getToContext(), Importer.Import(CE->getTypeSourceInfo()), - Importer.Import(CE->getLParenLoc()), llvm::makeArrayRef(ToArgs), - Importer.Import(CE->getRParenLoc())); + Importer.getToContext(), ToTypeSourceInfo, ToLParenLoc, + llvm::makeArrayRef(ToArgs), ToRParenLoc); } -Expr *ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { - auto *NamingClass = - cast_or_null<CXXRecordDecl>(Importer.Import(E->getNamingClass())); - if (E->getNamingClass() && !NamingClass) - return nullptr; +ExpectedStmt +ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { + Expected<CXXRecordDecl *> ToNamingClassOrErr = import(E->getNamingClass()); + if (!ToNamingClassOrErr) + return ToNamingClassOrErr.takeError(); - DeclarationName Name = Importer.Import(E->getName()); - if (E->getName() && !Name) - return nullptr; + auto ToQualifierLocOrErr = import(E->getQualifierLoc()); + if (!ToQualifierLocOrErr) + return ToQualifierLocOrErr.takeError(); - DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc())); + auto ToNameInfoOrErr = importSeq(E->getName(), E->getNameLoc()); + if (!ToNameInfoOrErr) + return ToNameInfoOrErr.takeError(); + DeclarationNameInfo ToNameInfo( + std::get<0>(*ToNameInfoOrErr), std::get<1>(*ToNameInfoOrErr)); // Import additional name location/type info. - ImportDeclarationNameLoc(E->getNameInfo(), NameInfo); + if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) + return std::move(Err); UnresolvedSet<8> ToDecls; - for (auto *D : E->decls()) { - if (auto *To = cast_or_null<NamedDecl>(Importer.Import(D))) - ToDecls.addDecl(To); + for (auto *D : E->decls()) + if (auto ToDOrErr = import(D)) + ToDecls.addDecl(cast<NamedDecl>(*ToDOrErr)); else - return nullptr; - } + return ToDOrErr.takeError(); - TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; - if (E->hasExplicitTemplateArgs()) { - if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), - E->template_arguments(), ToTAInfo)) - return nullptr; - ResInfo = &ToTAInfo; - } + if (E->hasExplicitTemplateArgs() && E->getTemplateKeywordLoc().isValid()) { + TemplateArgumentListInfo ToTAInfo; + if (Error Err = ImportTemplateArgumentListInfo( + E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(), + ToTAInfo)) + return std::move(Err); + + ExpectedSLoc ToTemplateKeywordLocOrErr = import(E->getTemplateKeywordLoc()); + if (!ToTemplateKeywordLocOrErr) + return ToTemplateKeywordLocOrErr.takeError(); - if (ResInfo || E->getTemplateKeywordLoc().isValid()) return UnresolvedLookupExpr::Create( - Importer.getToContext(), NamingClass, - Importer.Import(E->getQualifierLoc()), - Importer.Import(E->getTemplateKeywordLoc()), NameInfo, E->requiresADL(), - ResInfo, ToDecls.begin(), ToDecls.end()); + Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, + *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, + ToDecls.begin(), ToDecls.end()); + } return UnresolvedLookupExpr::Create( - Importer.getToContext(), NamingClass, - Importer.Import(E->getQualifierLoc()), NameInfo, E->requiresADL(), - E->isOverloaded(), ToDecls.begin(), ToDecls.end()); -} - -Expr *ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { - DeclarationName Name = Importer.Import(E->getName()); - if (!E->getName().isEmpty() && Name.isEmpty()) - return nullptr; - DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc())); + Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, + ToNameInfo, E->requiresADL(), E->isOverloaded(), ToDecls.begin(), + ToDecls.end()); +} + +ExpectedStmt +ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { + auto Imp1 = importSeq( + E->getType(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getTemplateKeywordLoc()); + if (!Imp1) + return Imp1.takeError(); + + QualType ToType; + SourceLocation ToOperatorLoc, ToTemplateKeywordLoc; + NestedNameSpecifierLoc ToQualifierLoc; + std::tie(ToType, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc) = *Imp1; + + auto Imp2 = importSeq(E->getName(), E->getNameLoc()); + if (!Imp2) + return Imp2.takeError(); + DeclarationNameInfo ToNameInfo(std::get<0>(*Imp2), std::get<1>(*Imp2)); // Import additional name location/type info. - ImportDeclarationNameLoc(E->getNameInfo(), NameInfo); - - QualType BaseType = Importer.Import(E->getType()); - if (!E->getType().isNull() && BaseType.isNull()) - return nullptr; + if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) + return std::move(Err); UnresolvedSet<8> ToDecls; - for (Decl *D : E->decls()) { - if (NamedDecl *To = cast_or_null<NamedDecl>(Importer.Import(D))) - ToDecls.addDecl(To); + for (Decl *D : E->decls()) + if (auto ToDOrErr = import(D)) + ToDecls.addDecl(cast<NamedDecl>(*ToDOrErr)); else - return nullptr; - } + return ToDOrErr.takeError(); TemplateArgumentListInfo ToTAInfo; TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) - return nullptr; + if (Error Err = + ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + return std::move(Err); ResInfo = &ToTAInfo; } - Expr *BaseE = E->isImplicitAccess() ? nullptr : Importer.Import(E->getBase()); - if (!BaseE && !E->isImplicitAccess() && E->getBase()) { - return nullptr; + Expr *ToBase = nullptr; + if (!E->isImplicitAccess()) { + if (ExpectedExpr ToBaseOrErr = import(E->getBase())) + ToBase = *ToBaseOrErr; + else + return ToBaseOrErr.takeError(); } return UnresolvedMemberExpr::Create( - Importer.getToContext(), E->hasUnresolvedUsing(), BaseE, BaseType, - E->isArrow(), Importer.Import(E->getOperatorLoc()), - Importer.Import(E->getQualifierLoc()), - Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo, - ToDecls.begin(), ToDecls.end()); + Importer.getToContext(), E->hasUnresolvedUsing(), ToBase, ToType, + E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, + ToNameInfo, ResInfo, ToDecls.begin(), ToDecls.end()); } -Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) { + auto Imp = importSeq(E->getCallee(), E->getType(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); - Expr *ToCallee = Importer.Import(E->getCallee()); - if (!ToCallee && E->getCallee()) - return nullptr; + Expr *ToCallee; + QualType ToType; + SourceLocation ToRParenLoc; + std::tie(ToCallee, ToType, ToRParenLoc) = *Imp; unsigned NumArgs = E->getNumArgs(); - SmallVector<Expr *, 2> ToArgs(NumArgs); - if (ImportContainerChecked(E->arguments(), ToArgs)) - return nullptr; - - auto **ToArgs_Copied = new (Importer.getToContext()) Expr*[NumArgs]; - - for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) - ToArgs_Copied[ai] = ToArgs[ai]; + llvm::SmallVector<Expr *, 2> ToArgs(NumArgs); + if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) + return std::move(Err); if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) { return new (Importer.getToContext()) CXXOperatorCallExpr( - Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, T, - OCE->getValueKind(), Importer.Import(OCE->getRParenLoc()), - OCE->getFPFeatures()); + Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, ToType, + OCE->getValueKind(), ToRParenLoc, OCE->getFPFeatures(), + OCE->getADLCallKind()); } - return new (Importer.getToContext()) - CallExpr(Importer.getToContext(), ToCallee, - llvm::makeArrayRef(ToArgs_Copied, NumArgs), T, E->getValueKind(), - Importer.Import(E->getRParenLoc())); + return new (Importer.getToContext()) CallExpr( + Importer.getToContext(), ToCallee, ToArgs, ToType, E->getValueKind(), + ToRParenLoc, /*MinNumArgs=*/0, E->getADLCallKind()); } -Optional<LambdaCapture> -ASTNodeImporter::ImportLambdaCapture(const LambdaCapture &From) { - VarDecl *Var = nullptr; - if (From.capturesVariable()) { - Var = cast_or_null<VarDecl>(Importer.Import(From.getCapturedVar())); - if (!Var) - return None; - } - - return LambdaCapture(Importer.Import(From.getLocation()), From.isImplicit(), - From.getCaptureKind(), Var, - From.isPackExpansion() - ? Importer.Import(From.getEllipsisLoc()) - : SourceLocation()); -} - -Expr *ASTNodeImporter::VisitLambdaExpr(LambdaExpr *LE) { - CXXRecordDecl *FromClass = LE->getLambdaClass(); - auto *ToClass = dyn_cast_or_null<CXXRecordDecl>(Importer.Import(FromClass)); - if (!ToClass) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { + CXXRecordDecl *FromClass = E->getLambdaClass(); + auto ToClassOrErr = import(FromClass); + if (!ToClassOrErr) + return ToClassOrErr.takeError(); + CXXRecordDecl *ToClass = *ToClassOrErr; // NOTE: lambda classes are created with BeingDefined flag set up. // It means that ImportDefinition doesn't work for them and we should fill it // manually. if (ToClass->isBeingDefined()) { for (auto FromField : FromClass->fields()) { - auto *ToField = cast_or_null<FieldDecl>(Importer.Import(FromField)); - if (!ToField) - return nullptr; + auto ToFieldOrErr = import(FromField); + if (!ToFieldOrErr) + return ToFieldOrErr.takeError(); } } - auto *ToCallOp = dyn_cast_or_null<CXXMethodDecl>( - Importer.Import(LE->getCallOperator())); - if (!ToCallOp) - return nullptr; + auto ToCallOpOrErr = import(E->getCallOperator()); + if (!ToCallOpOrErr) + return ToCallOpOrErr.takeError(); ToClass->completeDefinition(); - unsigned NumCaptures = LE->capture_size(); - SmallVector<LambdaCapture, 8> Captures; - Captures.reserve(NumCaptures); - for (const auto &FromCapture : LE->captures()) { - if (auto ToCapture = ImportLambdaCapture(FromCapture)) - Captures.push_back(*ToCapture); + SmallVector<LambdaCapture, 8> ToCaptures; + ToCaptures.reserve(E->capture_size()); + for (const auto &FromCapture : E->captures()) { + if (auto ToCaptureOrErr = import(FromCapture)) + ToCaptures.push_back(*ToCaptureOrErr); else - return nullptr; + return ToCaptureOrErr.takeError(); } - SmallVector<Expr *, 8> InitCaptures(NumCaptures); - if (ImportContainerChecked(LE->capture_inits(), InitCaptures)) - return nullptr; + SmallVector<Expr *, 8> ToCaptureInits(E->capture_size()); + if (Error Err = ImportContainerChecked(E->capture_inits(), ToCaptureInits)) + return std::move(Err); + + auto Imp = importSeq( + E->getIntroducerRange(), E->getCaptureDefaultLoc(), E->getEndLoc()); + if (!Imp) + return Imp.takeError(); + + SourceRange ToIntroducerRange; + SourceLocation ToCaptureDefaultLoc, ToEndLoc; + std::tie(ToIntroducerRange, ToCaptureDefaultLoc, ToEndLoc) = *Imp; return LambdaExpr::Create( - Importer.getToContext(), ToClass, - Importer.Import(LE->getIntroducerRange()), LE->getCaptureDefault(), - Importer.Import(LE->getCaptureDefaultLoc()), Captures, - LE->hasExplicitParameters(), LE->hasExplicitResultType(), InitCaptures, - Importer.Import(LE->getEndLoc()), LE->containsUnexpandedParameterPack()); + Importer.getToContext(), ToClass, ToIntroducerRange, + E->getCaptureDefault(), ToCaptureDefaultLoc, ToCaptures, + E->hasExplicitParameters(), E->hasExplicitResultType(), ToCaptureInits, + ToEndLoc, E->containsUnexpandedParameterPack()); } -Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { - QualType T = Importer.Import(ILE->getType()); - if (T.isNull()) - return nullptr; - SmallVector<Expr *, 4> Exprs(ILE->getNumInits()); - if (ImportContainerChecked(ILE->inits(), Exprs)) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitInitListExpr(InitListExpr *E) { + auto Imp = importSeq(E->getLBraceLoc(), E->getRBraceLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToLBraceLoc, ToRBraceLoc; + QualType ToType; + std::tie(ToLBraceLoc, ToRBraceLoc, ToType) = *Imp; + + SmallVector<Expr *, 4> ToExprs(E->getNumInits()); + if (Error Err = ImportContainerChecked(E->inits(), ToExprs)) + return std::move(Err); ASTContext &ToCtx = Importer.getToContext(); InitListExpr *To = new (ToCtx) InitListExpr( - ToCtx, Importer.Import(ILE->getLBraceLoc()), - Exprs, Importer.Import(ILE->getLBraceLoc())); - To->setType(T); + ToCtx, ToLBraceLoc, ToExprs, ToRBraceLoc); + To->setType(ToType); - if (ILE->hasArrayFiller()) { - Expr *Filler = Importer.Import(ILE->getArrayFiller()); - if (!Filler) - return nullptr; - To->setArrayFiller(Filler); + if (E->hasArrayFiller()) { + if (ExpectedExpr ToFillerOrErr = import(E->getArrayFiller())) + To->setArrayFiller(*ToFillerOrErr); + else + return ToFillerOrErr.takeError(); } - if (FieldDecl *FromFD = ILE->getInitializedFieldInUnion()) { - auto *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD)); - if (!ToFD) - return nullptr; - To->setInitializedFieldInUnion(ToFD); + if (FieldDecl *FromFD = E->getInitializedFieldInUnion()) { + if (auto ToFDOrErr = import(FromFD)) + To->setInitializedFieldInUnion(*ToFDOrErr); + else + return ToFDOrErr.takeError(); } - if (InitListExpr *SyntForm = ILE->getSyntacticForm()) { - auto *ToSyntForm = cast_or_null<InitListExpr>(Importer.Import(SyntForm)); - if (!ToSyntForm) - return nullptr; - To->setSyntacticForm(ToSyntForm); + if (InitListExpr *SyntForm = E->getSyntacticForm()) { + if (auto ToSyntFormOrErr = import(SyntForm)) + To->setSyntacticForm(*ToSyntFormOrErr); + else + return ToSyntFormOrErr.takeError(); } // Copy InitListExprBitfields, which are not handled in the ctor of // InitListExpr. - To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator()); + To->sawArrayRangeDesignator(E->hadArrayRangeDesignator()); return To; } -Expr *ASTNodeImporter::VisitCXXStdInitializerListExpr( +ExpectedStmt ASTNodeImporter::VisitCXXStdInitializerListExpr( CXXStdInitializerListExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - Expr *SE = Importer.Import(E->getSubExpr()); - if (!SE) - return nullptr; + ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); + if (!ToSubExprOrErr) + return ToSubExprOrErr.takeError(); - return new (Importer.getToContext()) CXXStdInitializerListExpr(T, SE); + return new (Importer.getToContext()) CXXStdInitializerListExpr( + *ToTypeOrErr, *ToSubExprOrErr); } -Expr *ASTNodeImporter::VisitCXXInheritedCtorInitExpr( +ExpectedStmt ASTNodeImporter::VisitCXXInheritedCtorInitExpr( CXXInheritedCtorInitExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; + auto Imp = importSeq(E->getLocation(), E->getType(), E->getConstructor()); + if (!Imp) + return Imp.takeError(); - auto *Ctor = cast_or_null<CXXConstructorDecl>(Importer.Import( - E->getConstructor())); - if (!Ctor) - return nullptr; + SourceLocation ToLocation; + QualType ToType; + CXXConstructorDecl *ToConstructor; + std::tie(ToLocation, ToType, ToConstructor) = *Imp; return new (Importer.getToContext()) CXXInheritedCtorInitExpr( - Importer.Import(E->getLocation()), T, Ctor, - E->constructsVBase(), E->inheritedFromVBase()); + ToLocation, ToType, ToConstructor, E->constructsVBase(), + E->inheritedFromVBase()); } -Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { - QualType ToType = Importer.Import(E->getType()); - if (ToType.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { + auto Imp = importSeq(E->getType(), E->getCommonExpr(), E->getSubExpr()); + if (!Imp) + return Imp.takeError(); - Expr *ToCommon = Importer.Import(E->getCommonExpr()); - if (!ToCommon && E->getCommonExpr()) - return nullptr; + QualType ToType; + Expr *ToCommonExpr, *ToSubExpr; + std::tie(ToType, ToCommonExpr, ToSubExpr) = *Imp; - Expr *ToSubExpr = Importer.Import(E->getSubExpr()); - if (!ToSubExpr && E->getSubExpr()) - return nullptr; - - return new (Importer.getToContext()) - ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr); + return new (Importer.getToContext()) ArrayInitLoopExpr( + ToType, ToCommonExpr, ToSubExpr); } -Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { - QualType ToType = Importer.Import(E->getType()); - if (ToType.isNull()) - return nullptr; - return new (Importer.getToContext()) ArrayInitIndexExpr(ToType); +ExpectedStmt ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + return new (Importer.getToContext()) ArrayInitIndexExpr(*ToTypeOrErr); } -Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { - auto *ToField = dyn_cast_or_null<FieldDecl>(Importer.Import(DIE->getField())); - if (!ToField && DIE->getField()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { + ExpectedSLoc ToBeginLocOrErr = import(E->getBeginLoc()); + if (!ToBeginLocOrErr) + return ToBeginLocOrErr.takeError(); + + auto ToFieldOrErr = import(E->getField()); + if (!ToFieldOrErr) + return ToFieldOrErr.takeError(); return CXXDefaultInitExpr::Create( - Importer.getToContext(), Importer.Import(DIE->getBeginLoc()), ToField); + Importer.getToContext(), *ToBeginLocOrErr, *ToFieldOrErr); } -Expr *ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { - QualType ToType = Importer.Import(E->getType()); - if (ToType.isNull() && !E->getType().isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { + auto Imp = importSeq( + E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten(), + E->getOperatorLoc(), E->getRParenLoc(), E->getAngleBrackets()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + Expr *ToSubExpr; + TypeSourceInfo *ToTypeInfoAsWritten; + SourceLocation ToOperatorLoc, ToRParenLoc; + SourceRange ToAngleBrackets; + std::tie( + ToType, ToSubExpr, ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, + ToAngleBrackets) = *Imp; + ExprValueKind VK = E->getValueKind(); CastKind CK = E->getCastKind(); - Expr *ToOp = Importer.Import(E->getSubExpr()); - if (!ToOp && E->getSubExpr()) - return nullptr; - CXXCastPath BasePath; - if (ImportCastPath(E, BasePath)) - return nullptr; - TypeSourceInfo *ToWritten = Importer.Import(E->getTypeInfoAsWritten()); - SourceLocation ToOperatorLoc = Importer.Import(E->getOperatorLoc()); - SourceLocation ToRParenLoc = Importer.Import(E->getRParenLoc()); - SourceRange ToAngleBrackets = Importer.Import(E->getAngleBrackets()); + auto ToBasePathOrErr = ImportCastPath(E); + if (!ToBasePathOrErr) + return ToBasePathOrErr.takeError(); if (isa<CXXStaticCastExpr>(E)) { return CXXStaticCastExpr::Create( - Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath, - ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); + Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), + ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else if (isa<CXXDynamicCastExpr>(E)) { return CXXDynamicCastExpr::Create( - Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath, - ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); + Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), + ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else if (isa<CXXReinterpretCastExpr>(E)) { return CXXReinterpretCastExpr::Create( - Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath, - ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); + Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), + ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else if (isa<CXXConstCastExpr>(E)) { - return CXXConstCastExpr::Create(Importer.getToContext(), ToType, VK, ToOp, - ToWritten, ToOperatorLoc, ToRParenLoc, - ToAngleBrackets); + return CXXConstCastExpr::Create( + Importer.getToContext(), ToType, VK, ToSubExpr, ToTypeInfoAsWritten, + ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else { - return nullptr; + llvm_unreachable("Unknown cast type"); + return make_error<ImportError>(); } } -Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( +ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - auto *Param = cast_or_null<NonTypeTemplateParmDecl>( - Importer.Import(E->getParameter())); - if (!Param) - return nullptr; + auto Imp = importSeq( + E->getType(), E->getExprLoc(), E->getParameter(), E->getReplacement()); + if (!Imp) + return Imp.takeError(); - Expr *Replacement = Importer.Import(E->getReplacement()); - if (!Replacement) - return nullptr; + QualType ToType; + SourceLocation ToExprLoc; + NonTypeTemplateParmDecl *ToParameter; + Expr *ToReplacement; + std::tie(ToType, ToExprLoc, ToParameter, ToReplacement) = *Imp; return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( - T, E->getValueKind(), Importer.Import(E->getExprLoc()), Param, - Replacement); + ToType, E->getValueKind(), ToExprLoc, ToParameter, ToReplacement); } -Expr *ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { - QualType ToType = Importer.Import(E->getType()); - if (ToType.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { + auto Imp = importSeq( + E->getType(), E->getBeginLoc(), E->getEndLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + SourceLocation ToBeginLoc, ToEndLoc; + std::tie(ToType, ToBeginLoc, ToEndLoc) = *Imp; SmallVector<TypeSourceInfo *, 4> ToArgs(E->getNumArgs()); - if (ImportContainerChecked(E->getArgs(), ToArgs)) - return nullptr; + if (Error Err = ImportContainerChecked(E->getArgs(), ToArgs)) + return std::move(Err); // According to Sema::BuildTypeTrait(), if E is value-dependent, // Value is always false. - bool ToValue = false; - if (!E->isValueDependent()) - ToValue = E->getValue(); + bool ToValue = (E->isValueDependent() ? false : E->getValue()); return TypeTraitExpr::Create( - Importer.getToContext(), ToType, Importer.Import(E->getBeginLoc()), - E->getTrait(), ToArgs, Importer.Import(E->getEndLoc()), ToValue); + Importer.getToContext(), ToType, ToBeginLoc, E->getTrait(), ToArgs, + ToEndLoc, ToValue); } -Expr *ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { - QualType ToType = Importer.Import(E->getType()); - if (ToType.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - if (E->isTypeOperand()) { - TypeSourceInfo *TSI = Importer.Import(E->getTypeOperandSourceInfo()); - if (!TSI) - return nullptr; + auto ToSourceRangeOrErr = import(E->getSourceRange()); + if (!ToSourceRangeOrErr) + return ToSourceRangeOrErr.takeError(); - return new (Importer.getToContext()) - CXXTypeidExpr(ToType, TSI, Importer.Import(E->getSourceRange())); + if (E->isTypeOperand()) { + if (auto ToTSIOrErr = import(E->getTypeOperandSourceInfo())) + return new (Importer.getToContext()) CXXTypeidExpr( + *ToTypeOrErr, *ToTSIOrErr, *ToSourceRangeOrErr); + else + return ToTSIOrErr.takeError(); } - Expr *Op = Importer.Import(E->getExprOperand()); - if (!Op) - return nullptr; + ExpectedExpr ToExprOperandOrErr = import(E->getExprOperand()); + if (!ToExprOperandOrErr) + return ToExprOperandOrErr.takeError(); - return new (Importer.getToContext()) - CXXTypeidExpr(ToType, Op, Importer.Import(E->getSourceRange())); + return new (Importer.getToContext()) CXXTypeidExpr( + *ToTypeOrErr, *ToExprOperandOrErr, *ToSourceRangeOrErr); } void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod) { - for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) - ToMethod->addOverriddenMethod( - cast<CXXMethodDecl>(Importer.Import(const_cast<CXXMethodDecl*>( - FromOverriddenMethod)))); + for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) { + if (auto ImportedOrErr = import(FromOverriddenMethod)) + ToMethod->getCanonicalDecl()->addOverriddenMethod(cast<CXXMethodDecl>( + (*ImportedOrErr)->getCanonicalDecl())); + else + consumeError(ImportedOrErr.takeError()); + } } ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, @@ -7021,30 +7687,44 @@ ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTImporter::~ASTImporter() = default; +Expected<QualType> ASTImporter::Import_New(QualType FromT) { + QualType ToT = Import(FromT); + if (ToT.isNull() && !FromT.isNull()) + return make_error<ImportError>(); + return ToT; +} QualType ASTImporter::Import(QualType FromT) { if (FromT.isNull()) return {}; - const Type *fromTy = FromT.getTypePtr(); + const Type *FromTy = FromT.getTypePtr(); // Check whether we've already imported this type. llvm::DenseMap<const Type *, const Type *>::iterator Pos - = ImportedTypes.find(fromTy); + = ImportedTypes.find(FromTy); if (Pos != ImportedTypes.end()) return ToContext.getQualifiedType(Pos->second, FromT.getLocalQualifiers()); // Import the type ASTNodeImporter Importer(*this); - QualType ToT = Importer.Visit(fromTy); - if (ToT.isNull()) - return ToT; + ExpectedType ToTOrErr = Importer.Visit(FromTy); + if (!ToTOrErr) { + llvm::consumeError(ToTOrErr.takeError()); + return {}; + } // Record the imported type. - ImportedTypes[fromTy] = ToT.getTypePtr(); + ImportedTypes[FromTy] = (*ToTOrErr).getTypePtr(); - return ToContext.getQualifiedType(ToT, FromT.getLocalQualifiers()); + return ToContext.getQualifiedType(*ToTOrErr, FromT.getLocalQualifiers()); } +Expected<TypeSourceInfo *> ASTImporter::Import_New(TypeSourceInfo *FromTSI) { + TypeSourceInfo *ToTSI = Import(FromTSI); + if (!ToTSI && FromTSI) + return llvm::make_error<ImportError>(); + return ToTSI; +} TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { if (!FromTSI) return FromTSI; @@ -7059,24 +7739,30 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { T, Import(FromTSI->getTypeLoc().getBeginLoc())); } +Expected<Attr *> ASTImporter::Import_New(const Attr *FromAttr) { + return Import(FromAttr); +} Attr *ASTImporter::Import(const Attr *FromAttr) { Attr *ToAttr = FromAttr->clone(ToContext); + // NOTE: Import of SourceRange may fail. ToAttr->setRange(Import(FromAttr->getRange())); return ToAttr; } -Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) { - llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD); - if (Pos != ImportedDecls.end()) { - Decl *ToD = Pos->second; - // FIXME: move this call to ImportDeclParts(). - ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD); - return ToD; - } else { +Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const { + auto Pos = ImportedDecls.find(FromD); + if (Pos != ImportedDecls.end()) + return Pos->second; + else return nullptr; - } } +Expected<Decl *> ASTImporter::Import_New(Decl *FromD) { + Decl *ToD = Import(FromD); + if (!ToD && FromD) + return llvm::make_error<ImportError>(); + return ToD; +} Decl *ASTImporter::Import(Decl *FromD) { if (!FromD) return nullptr; @@ -7092,9 +7778,12 @@ Decl *ASTImporter::Import(Decl *FromD) { } // Import the type. - ToD = Importer.Visit(FromD); - if (!ToD) + ExpectedDecl ToDOrErr = Importer.Visit(FromD); + if (!ToDOrErr) { + llvm::consumeError(ToDOrErr.takeError()); return nullptr; + } + ToD = *ToDOrErr; // Notify subclasses. Imported(FromD, ToD); @@ -7103,7 +7792,7 @@ Decl *ASTImporter::Import(Decl *FromD) { return ToD; } -DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { +Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) { if (!FromDC) return FromDC; @@ -7118,8 +7807,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { if (ToRecord->isCompleteDefinition()) { // Do nothing. } else if (FromRecord->isCompleteDefinition()) { - ASTNodeImporter(*this).ImportDefinition(FromRecord, ToRecord, - ASTNodeImporter::IDK_Basic); + if (Error Err = ASTNodeImporter(*this).ImportDefinition( + FromRecord, ToRecord, ASTNodeImporter::IDK_Basic)) + return std::move(Err); } else { CompleteDecl(ToRecord); } @@ -7128,8 +7818,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { if (ToEnum->isCompleteDefinition()) { // Do nothing. } else if (FromEnum->isCompleteDefinition()) { - ASTNodeImporter(*this).ImportDefinition(FromEnum, ToEnum, - ASTNodeImporter::IDK_Basic); + if (Error Err = ASTNodeImporter(*this).ImportDefinition( + FromEnum, ToEnum, ASTNodeImporter::IDK_Basic)) + return std::move(Err); } else { CompleteDecl(ToEnum); } @@ -7138,8 +7829,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { if (ToClass->getDefinition()) { // Do nothing. } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) { - ASTNodeImporter(*this).ImportDefinition(FromDef, ToClass, - ASTNodeImporter::IDK_Basic); + if (Error Err = ASTNodeImporter(*this).ImportDefinition( + FromDef, ToClass, ASTNodeImporter::IDK_Basic)) + return std::move(Err); } else { CompleteDecl(ToClass); } @@ -7148,8 +7840,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { if (ToProto->getDefinition()) { // Do nothing. } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) { - ASTNodeImporter(*this).ImportDefinition(FromDef, ToProto, - ASTNodeImporter::IDK_Basic); + if (Error Err = ASTNodeImporter(*this).ImportDefinition( + FromDef, ToProto, ASTNodeImporter::IDK_Basic)) + return std::move(Err); } else { CompleteDecl(ToProto); } @@ -7158,6 +7851,12 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { return ToDC; } +Expected<Expr *> ASTImporter::Import_New(Expr *FromE) { + Expr *ToE = Import(FromE); + if (!ToE && FromE) + return llvm::make_error<ImportError>(); + return ToE; +} Expr *ASTImporter::Import(Expr *FromE) { if (!FromE) return nullptr; @@ -7165,6 +7864,12 @@ Expr *ASTImporter::Import(Expr *FromE) { return cast_or_null<Expr>(Import(cast<Stmt>(FromE))); } +Expected<Stmt *> ASTImporter::Import_New(Stmt *FromS) { + Stmt *ToS = Import(FromS); + if (!ToS && FromS) + return llvm::make_error<ImportError>(); + return ToS; +} Stmt *ASTImporter::Import(Stmt *FromS) { if (!FromS) return nullptr; @@ -7174,13 +7879,15 @@ Stmt *ASTImporter::Import(Stmt *FromS) { if (Pos != ImportedStmts.end()) return Pos->second; - // Import the type + // Import the statement. ASTNodeImporter Importer(*this); - Stmt *ToS = Importer.Visit(FromS); - if (!ToS) + ExpectedStmt ToSOrErr = Importer.Visit(FromS); + if (!ToSOrErr) { + llvm::consumeError(ToSOrErr.takeError()); return nullptr; + } - if (auto *ToE = dyn_cast<Expr>(ToS)) { + if (auto *ToE = dyn_cast<Expr>(*ToSOrErr)) { auto *FromE = cast<Expr>(FromS); // Copy ExprBitfields, which may not be handled in Expr subclasses // constructors. @@ -7194,10 +7901,17 @@ Stmt *ASTImporter::Import(Stmt *FromS) { } // Record the imported declaration. - ImportedStmts[FromS] = ToS; - return ToS; + ImportedStmts[FromS] = *ToSOrErr; + return *ToSOrErr; } +Expected<NestedNameSpecifier *> +ASTImporter::Import_New(NestedNameSpecifier *FromNNS) { + NestedNameSpecifier *ToNNS = Import(FromNNS); + if (!ToNNS && FromNNS) + return llvm::make_error<ImportError>(); + return ToNNS; +} NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { if (!FromNNS) return nullptr; @@ -7251,6 +7965,11 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { llvm_unreachable("Invalid nested name specifier kind"); } +Expected<NestedNameSpecifierLoc> +ASTImporter::Import_New(NestedNameSpecifierLoc FromNNS) { + NestedNameSpecifierLoc ToNNS = Import(FromNNS); + return ToNNS; +} NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { // Copied from NestedNameSpecifier mostly. SmallVector<NestedNameSpecifierLoc , 8> NestedNames; @@ -7322,6 +8041,12 @@ NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { return Builder.getWithLocInContext(getToContext()); } +Expected<TemplateName> ASTImporter::Import_New(TemplateName From) { + TemplateName To = Import(From); + if (To.isNull() && !From.isNull()) + return llvm::make_error<ImportError>(); + return To; +} TemplateName ASTImporter::Import(TemplateName From) { switch (From.getKind()) { case TemplateName::Template: @@ -7398,18 +8123,26 @@ TemplateName ASTImporter::Import(TemplateName From) { return {}; ASTNodeImporter Importer(*this); - TemplateArgument ArgPack + Expected<TemplateArgument> ArgPack = Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); - if (ArgPack.isNull()) + if (!ArgPack) { + llvm::consumeError(ArgPack.takeError()); return {}; + } - return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack); + return ToContext.getSubstTemplateTemplateParmPack(Param, *ArgPack); } } llvm_unreachable("Invalid template name kind"); } +Expected<SourceLocation> ASTImporter::Import_New(SourceLocation FromLoc) { + SourceLocation ToLoc = Import(FromLoc); + if (ToLoc.isInvalid() && !FromLoc.isInvalid()) + return llvm::make_error<ImportError>(); + return ToLoc; +} SourceLocation ASTImporter::Import(SourceLocation FromLoc) { if (FromLoc.isInvalid()) return {}; @@ -7424,10 +8157,20 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) { return ToSM.getComposedLoc(ToFileID, Decomposed.second); } +Expected<SourceRange> ASTImporter::Import_New(SourceRange FromRange) { + SourceRange ToRange = Import(FromRange); + return ToRange; +} SourceRange ASTImporter::Import(SourceRange FromRange) { return SourceRange(Import(FromRange.getBegin()), Import(FromRange.getEnd())); } +Expected<FileID> ASTImporter::Import_New(FileID FromID) { + FileID ToID = Import(FromID); + if (ToID.isInvalid() && FromID.isValid()) + return llvm::make_error<ImportError>(); + return ToID; +} FileID ASTImporter::Import(FileID FromID) { llvm::DenseMap<FileID, FileID>::iterator Pos = ImportedFileIDs.find(FromID); if (Pos != ImportedFileIDs.end()) @@ -7485,6 +8228,13 @@ FileID ASTImporter::Import(FileID FromID) { return ToID; } +Expected<CXXCtorInitializer *> +ASTImporter::Import_New(CXXCtorInitializer *From) { + CXXCtorInitializer *To = Import(From); + if (!To && From) + return llvm::make_error<ImportError>(); + return To; +} CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { Expr *ToExpr = Import(From->getInit()); if (!ToExpr && From->getInit()) @@ -7530,6 +8280,13 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { } } +Expected<CXXBaseSpecifier *> +ASTImporter::Import_New(const CXXBaseSpecifier *From) { + CXXBaseSpecifier *To = Import(From); + if (!To && From) + return llvm::make_error<ImportError>(); + return To; +} CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec); if (Pos != ImportedCXXBaseSpecifiers.end()) @@ -7545,50 +8302,62 @@ CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { return Imported; } -void ASTImporter::ImportDefinition(Decl *From) { +Error ASTImporter::ImportDefinition_New(Decl *From) { Decl *To = Import(From); if (!To) - return; + return llvm::make_error<ImportError>(); if (auto *FromDC = cast<DeclContext>(From)) { ASTNodeImporter Importer(*this); if (auto *ToRecord = dyn_cast<RecordDecl>(To)) { if (!ToRecord->getDefinition()) { - Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord, - ASTNodeImporter::IDK_Everything); - return; + return Importer.ImportDefinition( + cast<RecordDecl>(FromDC), ToRecord, + ASTNodeImporter::IDK_Everything); } } if (auto *ToEnum = dyn_cast<EnumDecl>(To)) { if (!ToEnum->getDefinition()) { - Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum, - ASTNodeImporter::IDK_Everything); - return; + return Importer.ImportDefinition( + cast<EnumDecl>(FromDC), ToEnum, ASTNodeImporter::IDK_Everything); } } if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) { if (!ToIFace->getDefinition()) { - Importer.ImportDefinition(cast<ObjCInterfaceDecl>(FromDC), ToIFace, - ASTNodeImporter::IDK_Everything); - return; + return Importer.ImportDefinition( + cast<ObjCInterfaceDecl>(FromDC), ToIFace, + ASTNodeImporter::IDK_Everything); } } if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) { if (!ToProto->getDefinition()) { - Importer.ImportDefinition(cast<ObjCProtocolDecl>(FromDC), ToProto, - ASTNodeImporter::IDK_Everything); - return; + return Importer.ImportDefinition( + cast<ObjCProtocolDecl>(FromDC), ToProto, + ASTNodeImporter::IDK_Everything); } } - Importer.ImportDeclContext(FromDC, true); + return Importer.ImportDeclContext(FromDC, true); } + + return Error::success(); } +void ASTImporter::ImportDefinition(Decl *From) { + Error Err = ImportDefinition_New(From); + llvm::consumeError(std::move(Err)); +} + +Expected<DeclarationName> ASTImporter::Import_New(DeclarationName FromName) { + DeclarationName ToName = Import(FromName); + if (!ToName && FromName) + return llvm::make_error<ImportError>(); + return ToName; +} DeclarationName ASTImporter::Import(DeclarationName FromName) { if (!FromName) return {}; @@ -7665,6 +8434,12 @@ IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { return ToId; } +Expected<Selector> ASTImporter::Import_New(Selector FromSel) { + Selector ToSel = Import(FromSel); + if (ToSel.isNull() && !FromSel.isNull()) + return llvm::make_error<ImportError>(); + return ToSel; +} Selector ASTImporter::Import(Selector FromSel) { if (FromSel.isNull()) return {}; diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index 9149006a20..d19b89bb95 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -911,7 +911,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } -/// Determine structural equivalence of two methodss. +/// Determine structural equivalence of two methods. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, CXXMethodDecl *Method1, CXXMethodDecl *Method2) { @@ -1016,7 +1016,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; // Compare the definitions of these two records. If either or both are - // incomplete, we assume that they are equivalent. + // incomplete (i.e. it is a forward decl), we assume that they are + // equivalent. D1 = D1->getDefinition(); D2 = D2->getDefinition(); if (!D1 || !D2) @@ -1031,6 +1032,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage()) return true; + // If one definition is currently being defined, we do not compare for + // equality and we assume that the decls are equal. + if (D1->isBeingDefined() || D2->isBeingDefined()) + return true; + if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) { if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) { if (D1CXX->hasExternalLexicalStorage() && diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 4f868a3af5..adeb9f7e64 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -39,6 +39,7 @@ add_clang_library(clangAST ExprObjC.cpp ExternalASTMerger.cpp ExternalASTSource.cpp + FormatString.cpp InheritViz.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp @@ -48,12 +49,15 @@ add_clang_library(clangAST NestedNameSpecifier.cpp NSAPI.cpp ODRHash.cpp + OSLog.cpp OpenMPClause.cpp ParentMap.cpp + PrintfFormatString.cpp QualTypeNames.cpp RawCommentList.cpp RecordLayout.cpp RecordLayoutBuilder.cpp + ScanfFormatString.cpp SelectorLocationsKind.cpp Stmt.cpp StmtCXX.cpp @@ -65,6 +69,7 @@ add_clang_library(clangAST StmtViz.cpp TemplateBase.cpp TemplateName.cpp + TextNodeDumper.cpp Type.cpp TypeLoc.cpp TypePrinter.cpp diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp index c1c04239f5..7f70b95e98 100644 --- a/lib/AST/CommentParser.cpp +++ b/lib/AST/CommentParser.cpp @@ -558,7 +558,6 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() { case tok::verbatim_block_begin: case tok::verbatim_line_name: case tok::eof: - assert(Content.size() != 0); break; // Block content or EOF ahead, finish this parapgaph. case tok::unknown_command: diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 272e49a799..b32e5d9aa0 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -14,6 +14,7 @@ #include "clang/AST/Decl.h" #include "Linkage.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CanonicalType.h" @@ -49,7 +50,6 @@ #include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Visibility.h" -#include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" @@ -725,7 +725,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // If we're paying attention to global visibility, apply // -finline-visibility-hidden if this is an inline method. if (useInlineVisibilityHidden(D)) - LV.mergeVisibility(HiddenVisibility, true); + LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false); } } @@ -915,7 +915,7 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D, // Note that we do this before merging information about // the class visibility. if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D)) - LV.mergeVisibility(HiddenVisibility, true); + LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false); } // If this class member has an explicit visibility attribute, the only @@ -1265,14 +1265,24 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, // If a function is hidden by -fvisibility-inlines-hidden option and // is not explicitly attributed as a hidden function, // we should not make static local variables in the function hidden. + LV = getLVForDecl(FD, computation); if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) && - !(!hasExplicitVisibilityAlready(computation) && - getExplicitVisibility(FD, computation))) { + !LV.isVisibilityExplicit()) { assert(cast<VarDecl>(D)->isStaticLocal()); - return LinkageInfo(VisibleNoLinkage, DefaultVisibility, false); + // If this was an implicitly hidden inline method, check again for + // explicit visibility on the parent class, and use that for static locals + // if present. + if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) + LV = getLVForDecl(MD->getParent(), computation); + if (!LV.isVisibilityExplicit()) { + Visibility globalVisibility = + computation.isValueVisibility() + ? Context.getLangOpts().getValueVisibilityMode() + : Context.getLangOpts().getTypeVisibilityMode(); + return LinkageInfo(VisibleNoLinkage, globalVisibility, + /*visibilityExplicit=*/false); + } } - - LV = getLVForDecl(FD, computation); } if (!isExternallyVisible(LV.getLinkage())) return LinkageInfo::none(); @@ -2361,6 +2371,14 @@ static DeclT *getDefinitionOrSelf(DeclT *D) { return D; } +bool VarDecl::isEscapingByref() const { + return hasAttr<BlocksAttr>() && NonParmVarDeclBits.EscapingByref; +} + +bool VarDecl::isNonEscapingByref() const { + return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref; +} + VarDecl *VarDecl::getTemplateInstantiationPattern() const { // If it's a variable template specialization, find the template or partial // specialization from which it was instantiated. @@ -2451,7 +2469,7 @@ bool VarDecl::isKnownToBeDefined() const { // // With CUDA relocatable device code enabled, these variables don't get // special handling; they're treated like regular extern variables. - if (LangOpts.CUDA && !LangOpts.CUDARelocatableDeviceCode && + if (LangOpts.CUDA && !LangOpts.GPURelocatableDeviceCode && hasExternalStorage() && hasAttr<CUDASharedAttr>() && isa<IncompleteArrayType>(getType())) return true; @@ -2558,7 +2576,7 @@ Expr *ParmVarDecl::getDefaultArg() { "Default argument is not yet instantiated!"); Expr *Arg = getInit(); - if (auto *E = dyn_cast_or_null<ExprWithCleanups>(Arg)) + if (auto *E = dyn_cast_or_null<FullExpr>(Arg)) return E->getSubExpr(); return Arg; @@ -2634,27 +2652,30 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, StartLoc), DeclContext(DK), redeclarable_base(C), ODRHash(0), EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) { - setStorageClass(S); - setInlineSpecified(isInlineSpecified); - setExplicitSpecified(false); - setVirtualAsWritten(false); - setPure(false); - setHasInheritedPrototype(false); - setHasWrittenPrototype(true); - setDeletedAsWritten(false); - setTrivial(false); - setTrivialForCall(false); - setDefaulted(false); - setExplicitlyDefaulted(false); - setHasImplicitReturnZero(false); - setLateTemplateParsed(false); - setConstexpr(isConstexprSpecified); - setInstantiationIsPending(false); - setUsesSEHTry(false); - setHasSkippedBody(false); - setWillHaveBody(false); - setIsMultiVersion(false); - setHasODRHash(false); + assert(T.isNull() || T->isFunctionType()); + FunctionDeclBits.SClass = S; + FunctionDeclBits.IsInline = isInlineSpecified; + FunctionDeclBits.IsInlineSpecified = isInlineSpecified; + FunctionDeclBits.IsExplicitSpecified = false; + FunctionDeclBits.IsVirtualAsWritten = false; + FunctionDeclBits.IsPure = false; + FunctionDeclBits.HasInheritedPrototype = false; + FunctionDeclBits.HasWrittenPrototype = true; + FunctionDeclBits.IsDeleted = false; + FunctionDeclBits.IsTrivial = false; + FunctionDeclBits.IsTrivialForCall = false; + FunctionDeclBits.IsDefaulted = false; + FunctionDeclBits.IsExplicitlyDefaulted = false; + FunctionDeclBits.HasImplicitReturnZero = false; + FunctionDeclBits.IsLateTemplateParsed = false; + FunctionDeclBits.IsConstexpr = isConstexprSpecified; + FunctionDeclBits.InstantiationIsPending = false; + FunctionDeclBits.UsesSEHTry = false; + FunctionDeclBits.HasSkippedBody = false; + FunctionDeclBits.WillHaveBody = false; + FunctionDeclBits.IsMultiVersion = false; + FunctionDeclBits.IsCopyDeductionCandidate = false; + FunctionDeclBits.HasODRHash = false; } void FunctionDecl::getNameForDiagnostic( @@ -2921,6 +2942,17 @@ bool FunctionDecl::isNoReturn() const { return false; } + +MultiVersionKind FunctionDecl::getMultiVersionKind() const { + if (hasAttr<TargetAttr>()) + return MultiVersionKind::Target; + if (hasAttr<CPUDispatchAttr>()) + return MultiVersionKind::CPUDispatch; + if (hasAttr<CPUSpecificAttr>()) + return MultiVersionKind::CPUSpecific; + return MultiVersionKind::None; +} + bool FunctionDecl::isCPUDispatchMultiVersion() const { return isMultiVersion() && hasAttr<CPUDispatchAttr>(); } @@ -2929,6 +2961,10 @@ bool FunctionDecl::isCPUSpecificMultiVersion() const { return isMultiVersion() && hasAttr<CPUSpecificAttr>(); } +bool FunctionDecl::isTargetMultiVersion() const { + return isMultiVersion() && hasAttr<TargetAttr>(); +} + void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { redeclarable_base::setPreviousDecl(PrevDecl); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index f5de359106..95babf7917 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -955,10 +955,7 @@ static Decl::Kind getKind(const Decl *D) { return D->getKind(); } static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); } int64_t Decl::getID() const { - Optional<int64_t> Out = getASTContext().getAllocator().identifyObject(this); - assert(Out && "Wrong allocator used"); - assert(*Out % alignof(Decl) == 0 && "Wrong alignment information"); - return *Out / alignof(Decl); + return getASTContext().getAllocator().identifyKnownAlignedObject<Decl>(this); } const FunctionType *Decl::getFunctionType(bool BlocksToo) const { @@ -1724,8 +1721,18 @@ void DeclContext::localUncachedLookup(DeclarationName Name, DeclContext *DeclContext::getRedeclContext() { DeclContext *Ctx = this; - // Skip through transparent contexts. - while (Ctx->isTransparentContext()) + + // In C, a record type is the redeclaration context for its fields only. If + // we arrive at a record context after skipping anything else, we should skip + // the record as well. Currently, this means skipping enumerations because + // they're the only transparent context that can exist within a struct or + // union. + bool SkipRecords = getDeclKind() == Decl::Kind::Enum && + !getParentASTContext().getLangOpts().CPlusPlus; + + // Skip through contexts to get to the redeclaration context. Transparent + // contexts are always skipped. + while ((SkipRecords && Ctx->isRecord()) || Ctx->isTransparentContext()) Ctx = Ctx->getParent(); return Ctx; } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 9bb6e3a013..33f159417b 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -2173,19 +2173,24 @@ CXXMethodDecl::overridden_methods() const { return getASTContext().overridden_methods(this); } +QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT, + const CXXRecordDecl *Decl) { + ASTContext &C = Decl->getASTContext(); + QualType ClassTy = C.getTypeDeclType(Decl); + ClassTy = C.getQualifiedType(ClassTy, FPT->getTypeQuals()); + return C.getPointerType(ClassTy); +} + QualType CXXMethodDecl::getThisType(ASTContext &C) const { // C++ 9.3.2p1: The type of this in a member function of a class X is X*. // If the member function is declared const, the type of this is const X*, // if the member function is declared volatile, the type of this is // volatile X*, and if the member function is declared const volatile, // the type of this is const volatile X*. - assert(isInstance() && "No 'this' for static methods!"); - QualType ClassTy = C.getTypeDeclType(getParent()); - ClassTy = C.getQualifiedType(ClassTy, - Qualifiers::fromCVRUMask(getTypeQualifiers())); - return C.getPointerType(ClassTy); + return CXXMethodDecl::getThisType(getType()->getAs<FunctionProtoType>(), + getParent()); } bool CXXMethodDecl::hasInlineBody() const { @@ -2246,6 +2251,11 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, : Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {} +int64_t CXXCtorInitializer::getID(const ASTContext &Context) const { + return Context.getAllocator() + .identifyKnownAlignedObject<CXXCtorInitializer>(this); +} + TypeLoc CXXCtorInitializer::getBaseClassLoc() const { if (isBaseInitializer()) return Initializee.get<TypeSourceInfo*>()->getTypeLoc(); diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 7fc275f90e..517851f9ee 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -1549,11 +1549,9 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { Out << "#pragma omp requires "; if (!D->clauselist_empty()) { - for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I) { - if (I != D->clauselist_begin()) - Out << ','; - Out << getOpenMPClauseName((*I)->getClauseKind()); - } + OMPClausePrinter Printer(Out, Policy); + for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I) + Printer.Visit(*I); } } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 8e4944607c..04e1803281 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -300,6 +300,40 @@ ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() { return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size()); } +void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) { + using Base = RedeclarableTemplateDecl; + + // If we haven't created a common pointer yet, then it can just be created + // with the usual method. + if (!Base::Common) + return; + + Common *ThisCommon = static_cast<Common *>(Base::Common); + Common *PrevCommon = nullptr; + SmallVector<FunctionTemplateDecl *, 8> PreviousDecls; + for (; Prev; Prev = Prev->getPreviousDecl()) { + if (Prev->Base::Common) { + PrevCommon = static_cast<Common *>(Prev->Base::Common); + break; + } + PreviousDecls.push_back(Prev); + } + + // If the previous redecl chain hasn't created a common pointer yet, then just + // use this common pointer. + if (!PrevCommon) { + for (auto *D : PreviousDecls) + D->Base::Common = ThisCommon; + return; + } + + // Ensure we don't leak any important state. + assert(ThisCommon->Specializations.size() == 0 && + "Can't merge incompatible declarations!"); + + Base::Common = PrevCommon; +} + //===----------------------------------------------------------------------===// // ClassTemplateDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 651981374d..5a80016850 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -28,7 +28,6 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/LiteralSupport.h" -#include "clang/Sema/SemaDiagnostic.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -351,7 +350,8 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK) : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), - D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) { + D(D), DNLoc(NameInfo.getInfo()) { + DeclRefExprBits.Loc = NameInfo.getLoc(); DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; if (QualifierLoc) { new (getTrailingObjects<NestedNameSpecifierLoc>()) @@ -458,20 +458,45 @@ SourceLocation DeclRefExpr::getEndLoc() const { return getNameInfo().getEndLoc(); } -PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, +PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, StringLiteral *SL) : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary, FNTy->isDependentType(), FNTy->isDependentType(), FNTy->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false), - Loc(L), Type(IT), FnName(SL) {} + /*ContainsUnexpandedParameterPack=*/false) { + PredefinedExprBits.Kind = IK; + assert((getIdentKind() == IK) && + "IdentKind do not fit in PredefinedExprBitfields!"); + bool HasFunctionName = SL != nullptr; + PredefinedExprBits.HasFunctionName = HasFunctionName; + PredefinedExprBits.Loc = L; + if (HasFunctionName) + setFunctionName(SL); +} + +PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName) + : Expr(PredefinedExprClass, Empty) { + PredefinedExprBits.HasFunctionName = HasFunctionName; +} -StringLiteral *PredefinedExpr::getFunctionName() { - return cast_or_null<StringLiteral>(FnName); +PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L, + QualType FNTy, IdentKind IK, + StringLiteral *SL) { + bool HasFunctionName = SL != nullptr; + void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName), + alignof(PredefinedExpr)); + return new (Mem) PredefinedExpr(L, FNTy, IK, SL); } -StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) { - switch (IT) { +PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx, + bool HasFunctionName) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName), + alignof(PredefinedExpr)); + return new (Mem) PredefinedExpr(EmptyShell(), HasFunctionName); +} + +StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) { + switch (IK) { case Func: return "__func__"; case Function: @@ -489,15 +514,15 @@ StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) { case PrettyFunctionNoVirtual: break; } - llvm_unreachable("Unknown ident type for PredefinedExpr"); + llvm_unreachable("Unknown ident kind for PredefinedExpr"); } // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. -std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { +std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) { ASTContext &Context = CurrentDecl->getASTContext(); - if (IT == PredefinedExpr::FuncDName) { + if (IK == PredefinedExpr::FuncDName) { if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) { std::unique_ptr<MangleContext> MC; MC.reset(Context.createMangleContext()); @@ -532,21 +557,21 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { llvm::raw_svector_ostream Out(Buffer); if (auto *DCBlock = dyn_cast<BlockDecl>(DC)) // For nested blocks, propagate up to the parent. - Out << ComputeName(IT, DCBlock); + Out << ComputeName(IK, DCBlock); else if (auto *DCDecl = dyn_cast<Decl>(DC)) - Out << ComputeName(IT, DCDecl) << "_block_invoke"; + Out << ComputeName(IK, DCDecl) << "_block_invoke"; return Out.str(); } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) { - if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && - IT != FuncSig && IT != LFuncSig) + if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual && + IK != FuncSig && IK != LFuncSig) return FD->getNameAsString(); SmallString<256> Name; llvm::raw_svector_ostream Out(Name); if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { - if (MD->isVirtual() && IT != PrettyFunctionNoVirtual) + if (MD->isVirtual() && IK != PrettyFunctionNoVirtual) Out << "virtual "; if (MD->isStatic()) Out << "static "; @@ -564,7 +589,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(AFT); - if (IT == FuncSig || IT == LFuncSig) { + if (IK == FuncSig || IK == LFuncSig) { switch (AFT->getCallConv()) { case CC_C: POut << "__cdecl "; break; case CC_X86StdCall: POut << "__stdcall "; break; @@ -589,7 +614,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (FT->isVariadic()) { if (FD->getNumParams()) POut << ", "; POut << "..."; - } else if ((IT == FuncSig || IT == LFuncSig || + } else if ((IK == FuncSig || IK == LFuncSig || !Context.getLangOpts().CPlusPlus) && !Decl->getNumParams()) { POut << "void"; @@ -688,7 +713,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { // CapturedDecl. if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) { const Decl *D = Decl::castFromDeclContext(DC); - return ComputeName(IT, D); + return ComputeName(IK, D); } llvm_unreachable("CapturedDecl not inside a function or method"); } @@ -713,7 +738,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { return Name.str().str(); } - if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) { + if (isa<TranslationUnitDecl>(CurrentDecl) && IK == PrettyFunction) { // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string. return "top level"; } @@ -861,66 +886,105 @@ double FloatingLiteral::getValueAsApproximateDouble() const { return V.convertToDouble(); } -int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind k) { - int CharByteWidth = 0; - switch(k) { - case Ascii: - case UTF8: - CharByteWidth = target.getCharWidth(); - break; - case Wide: - CharByteWidth = target.getWCharWidth(); - break; - case UTF16: - CharByteWidth = target.getChar16Width(); - break; - case UTF32: - CharByteWidth = target.getChar32Width(); - break; +unsigned StringLiteral::mapCharByteWidth(TargetInfo const &Target, + StringKind SK) { + unsigned CharByteWidth = 0; + switch (SK) { + case Ascii: + case UTF8: + CharByteWidth = Target.getCharWidth(); + break; + case Wide: + CharByteWidth = Target.getWCharWidth(); + break; + case UTF16: + CharByteWidth = Target.getChar16Width(); + break; + case UTF32: + CharByteWidth = Target.getChar32Width(); + break; } assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple"); CharByteWidth /= 8; - assert((CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4) - && "character byte widths supported are 1, 2, and 4 only"); + assert((CharByteWidth == 1 || CharByteWidth == 2 || CharByteWidth == 4) && + "The only supported character byte widths are 1,2 and 4!"); return CharByteWidth; } -StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, - const SourceLocation *Loc, - unsigned NumStrs) { - assert(C.getAsConstantArrayType(Ty) && +StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str, + StringKind Kind, bool Pascal, QualType Ty, + const SourceLocation *Loc, + unsigned NumConcatenated) + : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, + false) { + assert(Ctx.getAsConstantArrayType(Ty) && "StringLiteral must be of constant array type!"); + unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind); + unsigned ByteLength = Str.size(); + assert((ByteLength % CharByteWidth == 0) && + "The size of the data must be a multiple of CharByteWidth!"); + + // Avoid the expensive division. The compiler should be able to figure it + // out by itself. However as of clang 7, even with the appropriate + // llvm_unreachable added just here, it is not able to do so. + unsigned Length; + switch (CharByteWidth) { + case 1: + Length = ByteLength; + break; + case 2: + Length = ByteLength / 2; + break; + case 4: + Length = ByteLength / 4; + break; + default: + llvm_unreachable("Unsupported character width!"); + } - // Allocate enough space for the StringLiteral plus an array of locations for - // any concatenated string tokens. - void *Mem = - C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), - alignof(StringLiteral)); - StringLiteral *SL = new (Mem) StringLiteral(Ty); + StringLiteralBits.Kind = Kind; + StringLiteralBits.CharByteWidth = CharByteWidth; + StringLiteralBits.IsPascal = Pascal; + StringLiteralBits.NumConcatenated = NumConcatenated; + *getTrailingObjects<unsigned>() = Length; - // OPTIMIZE: could allocate this appended to the StringLiteral. - SL->setString(C,Str,Kind,Pascal); + // Initialize the trailing array of SourceLocation. + // This is safe since SourceLocation is POD-like. + std::memcpy(getTrailingObjects<SourceLocation>(), Loc, + NumConcatenated * sizeof(SourceLocation)); - SL->TokLocs[0] = Loc[0]; - SL->NumConcatenated = NumStrs; + // Initialize the trailing array of char holding the string data. + std::memcpy(getTrailingObjects<char>(), Str.data(), ByteLength); +} - if (NumStrs != 1) - memcpy(&SL->TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1)); - return SL; +StringLiteral::StringLiteral(EmptyShell Empty, unsigned NumConcatenated, + unsigned Length, unsigned CharByteWidth) + : Expr(StringLiteralClass, Empty) { + StringLiteralBits.CharByteWidth = CharByteWidth; + StringLiteralBits.NumConcatenated = NumConcatenated; + *getTrailingObjects<unsigned>() = Length; } -StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C, - unsigned NumStrs) { - void *Mem = - C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), - alignof(StringLiteral)); - StringLiteral *SL = - new (Mem) StringLiteral(C.adjustStringLiteralBaseType(QualType())); - SL->CharByteWidth = 0; - SL->Length = 0; - SL->NumConcatenated = NumStrs; - return SL; +StringLiteral *StringLiteral::Create(const ASTContext &Ctx, StringRef Str, + StringKind Kind, bool Pascal, QualType Ty, + const SourceLocation *Loc, + unsigned NumConcatenated) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned, SourceLocation, char>( + 1, NumConcatenated, Str.size()), + alignof(StringLiteral)); + return new (Mem) + StringLiteral(Ctx, Str, Kind, Pascal, Ty, Loc, NumConcatenated); +} + +StringLiteral *StringLiteral::CreateEmpty(const ASTContext &Ctx, + unsigned NumConcatenated, + unsigned Length, + unsigned CharByteWidth) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned, SourceLocation, char>( + 1, NumConcatenated, Length * CharByteWidth), + alignof(StringLiteral)); + return new (Mem) + StringLiteral(EmptyShell(), NumConcatenated, Length, CharByteWidth); } void StringLiteral::outputString(raw_ostream &OS) const { @@ -1019,42 +1083,6 @@ void StringLiteral::outputString(raw_ostream &OS) const { OS << '"'; } -void StringLiteral::setString(const ASTContext &C, StringRef Str, - StringKind Kind, bool IsPascal) { - //FIXME: we assume that the string data comes from a target that uses the same - // code unit size and endianness for the type of string. - this->Kind = Kind; - this->IsPascal = IsPascal; - - CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind); - assert((Str.size()%CharByteWidth == 0) - && "size of data must be multiple of CharByteWidth"); - Length = Str.size()/CharByteWidth; - - switch(CharByteWidth) { - case 1: { - char *AStrData = new (C) char[Length]; - std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData)); - StrData.asChar = AStrData; - break; - } - case 2: { - uint16_t *AStrData = new (C) uint16_t[Length]; - std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData)); - StrData.asUInt16 = AStrData; - break; - } - case 4: { - uint32_t *AStrData = new (C) uint32_t[Length]; - std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData)); - StrData.asUInt32 = AStrData; - break; - } - default: - llvm_unreachable("unsupported CharByteWidth"); - } -} - /// getLocationOfByte - Return a source location that points to the specified /// byte of this string literal. /// @@ -1076,7 +1104,8 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken, unsigned *StartTokenByteOffset) const { - assert((Kind == StringLiteral::Ascii || Kind == StringLiteral::UTF8) && + assert((getKind() == StringLiteral::Ascii || + getKind() == StringLiteral::UTF8) && "Only narrow string literals are currently supported"); // Loop over all of the tokens in this string until we find the one that @@ -1144,8 +1173,6 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, } } - - /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++". StringRef UnaryOperator::getOpcodeStr(Opcode Op) { @@ -1194,14 +1221,19 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t, - ExprValueKind VK, SourceLocation rparenloc) + ExprValueKind VK, SourceLocation rparenloc, + unsigned MinNumArgs, ADLCallKind UsesADL) : Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(), fn->isValueDependent(), fn->isInstantiationDependent(), fn->containsUnexpandedParameterPack()), - NumArgs(args.size()) { + RParenLoc(rparenloc) { + CallExprBits.UsesADL = static_cast<bool>(UsesADL); + NumArgs = std::max<unsigned>(args.size(), MinNumArgs); unsigned NumPreArgs = preargs.size(); - SubExprs = new (C) Stmt *[args.size()+PREARGS_START+NumPreArgs]; + CallExprBits.NumPreArgs = NumPreArgs; + + SubExprs = new (C) Stmt *[NumArgs + PREARGS_START + NumPreArgs]; SubExprs[FN] = fn; for (unsigned i = 0; i != NumPreArgs; ++i) { updateDependenciesFromArg(preargs[i]); @@ -1211,32 +1243,34 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, updateDependenciesFromArg(args[i]); SubExprs[i+PREARGS_START+NumPreArgs] = args[i]; } - - CallExprBits.NumPreArgs = NumPreArgs; - RParenLoc = rparenloc; + for (unsigned i = args.size(); i != NumArgs; ++i) { + SubExprs[i + PREARGS_START + NumPreArgs] = nullptr; + } } CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> args, QualType t, ExprValueKind VK, - SourceLocation rparenloc) - : CallExpr(C, SC, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) {} + SourceLocation rparenloc, unsigned MinNumArgs, + ADLCallKind UsesADL) + : CallExpr(C, SC, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc, + MinNumArgs, UsesADL) {} CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args, - QualType t, ExprValueKind VK, SourceLocation rparenloc) - : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) { -} - -CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) - : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {} + QualType t, ExprValueKind VK, SourceLocation rparenloc, + unsigned MinNumArgs, ADLCallKind UsesADL) + : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc, + MinNumArgs, UsesADL) {} CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, - EmptyShell Empty) - : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { - // FIXME: Why do we allocate this? - SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs](); + unsigned NumArgs, EmptyShell Empty) + : Expr(SC, Empty), NumArgs(NumArgs) { CallExprBits.NumPreArgs = NumPreArgs; + SubExprs = new (C) Stmt *[NumArgs + PREARGS_START + NumPreArgs]; } +CallExpr::CallExpr(const ASTContext &C, unsigned NumArgs, EmptyShell Empty) + : CallExpr(C, CallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {} + void CallExpr::updateDependenciesFromArg(Expr *Arg) { if (Arg->isTypeDependent()) ExprBits.TypeDependent = true; @@ -1280,35 +1314,6 @@ Decl *Expr::getReferencedDeclOfCallee() { return nullptr; } -/// setNumArgs - This changes the number of arguments present in this call. -/// Any orphaned expressions are deleted by this, and any new operands are set -/// to null. -void CallExpr::setNumArgs(const ASTContext& C, unsigned NumArgs) { - // No change, just return. - if (NumArgs == getNumArgs()) return; - - // If shrinking # arguments, just delete the extras and forgot them. - if (NumArgs < getNumArgs()) { - this->NumArgs = NumArgs; - return; - } - - // Otherwise, we are growing the # arguments. New an bigger argument array. - unsigned NumPreArgs = getNumPreArgs(); - Stmt **NewSubExprs = new (C) Stmt*[NumArgs+PREARGS_START+NumPreArgs]; - // Copy over args. - for (unsigned i = 0; i != getNumArgs()+PREARGS_START+NumPreArgs; ++i) - NewSubExprs[i] = SubExprs[i]; - // Null out new args. - for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs; - i != NumArgs+PREARGS_START+NumPreArgs; ++i) - NewSubExprs[i] = nullptr; - - if (SubExprs) C.Deallocate(SubExprs); - SubExprs = NewSubExprs; - this->NumArgs = NumArgs; -} - /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If /// not, return 0. unsigned CallExpr::getBuiltinCallee() const { @@ -1446,7 +1451,7 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( // 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 (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) { if (!isValueDependent() || !isInstantiationDependent()) { E = E->IgnoreParens(); @@ -1502,7 +1507,7 @@ MemberExpr *MemberExpr::Create( QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) E->setInstantiationDependent(true); - E->HasQualifierOrFoundDecl = true; + E->MemberExprBits.HasQualifierOrFoundDecl = true; MemberExprNameQualifier *NQ = E->getTrailingObjects<MemberExprNameQualifier>(); @@ -1510,7 +1515,8 @@ MemberExpr *MemberExpr::Create( NQ->FoundDecl = founddecl; } - E->HasTemplateKWAndArgsInfo = (targs || TemplateKWLoc.isValid()); + E->MemberExprBits.HasTemplateKWAndArgsInfo = + (targs || TemplateKWLoc.isValid()); if (targs) { bool Dependent = false; @@ -1605,13 +1611,18 @@ bool CastExpr::CastConsistency() const { assert(getSubExpr()->getType()->isFunctionType()); goto CheckNoBasePath; - case CK_AddressSpaceConversion: - assert(getType()->isPointerType() || getType()->isBlockPointerType()); - assert(getSubExpr()->getType()->isPointerType() || - getSubExpr()->getType()->isBlockPointerType()); - assert(getType()->getPointeeType().getAddressSpace() != - getSubExpr()->getType()->getPointeeType().getAddressSpace()); - LLVM_FALLTHROUGH; + case CK_AddressSpaceConversion: { + auto Ty = getType(); + auto SETy = getSubExpr()->getType(); + assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy)); + if (!isGLValue()) + Ty = Ty->getPointeeType(); + if (!isGLValue()) + SETy = SETy->getPointeeType(); + assert(!Ty.isNull() && !SETy.isNull() && + Ty.getAddressSpace() != SETy.getAddressSpace()); + goto CheckNoBasePath; + } // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: @@ -1641,9 +1652,9 @@ bool CastExpr::CastConsistency() const { case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: - case CK_ZeroToOCLEvent: - case CK_ZeroToOCLQueue: + case CK_ZeroToOCLOpaqueType: case CK_IntToOCLSampler: + case CK_FixedPointCast: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; @@ -1661,6 +1672,7 @@ bool CastExpr::CastConsistency() const { case CK_LValueBitCast: // -> bool& case CK_UserDefinedConversion: // operator bool() case CK_BuiltinFnToFnPtr: + case CK_FixedPointToBoolean: CheckNoBasePath: assert(path_empty() && "Cast kind should not have a base path!"); break; @@ -2559,6 +2571,10 @@ Expr *Expr::IgnoreParenCasts() { E = NTTP->getReplacement(); continue; } + if (FullExpr *FE = dyn_cast<FullExpr>(E)) { + E = FE->getSubExpr(); + continue; + } return E; } } @@ -2580,6 +2596,10 @@ Expr *Expr::IgnoreCasts() { E = NTTP->getReplacement(); continue; } + if (FullExpr *FE = dyn_cast<FullExpr>(E)) { + E = FE->getSubExpr(); + continue; + } return E; } } @@ -2605,6 +2625,9 @@ Expr *Expr::IgnoreParenLValueCasts() { = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { E = NTTP->getReplacement(); continue; + } else if (FullExpr *FE = dyn_cast<FullExpr>(E)) { + E = FE->getSubExpr(); + continue; } break; } @@ -2646,6 +2669,10 @@ Expr *Expr::IgnoreParenImpCasts() { E = NTTP->getReplacement(); continue; } + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) { + E = CE->getSubExpr(); + continue; + } return E; } } @@ -2870,6 +2897,12 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, break; } + case ConstantExprClass: { + // FIXME: We should be able to return "true" here, but it can lead to extra + // error messages. E.g. in Sema/array-init.c. + const Expr *Exp = cast<ConstantExpr>(this)->getSubExpr(); + return Exp->isConstantInitializer(Ctx, false, Culprit); + } case CompoundLiteralExprClass: { // This handles gcc's extension that allows global initializers like // "struct x {int x;} x = (struct x) {};". @@ -2909,8 +2942,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, const Expr *Elt = ILE->getInit(ElementNo++); if (Field->isBitField()) { // Bitfields have to evaluate to an integer. - llvm::APSInt ResultTmp; - if (!Elt->EvaluateAsInt(ResultTmp, Ctx)) { + EvalResult Result; + if (!Elt->EvaluateAsInt(Result, Ctx)) { if (Culprit) *Culprit = Elt; return false; @@ -3095,6 +3128,11 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, // These never have a side-effect. return false; + case ConstantExprClass: + // FIXME: Move this into the "return false;" block above. + return cast<ConstantExpr>(this)->getSubExpr()->HasSideEffects( + Ctx, IncludePossibleEffects); + case CallExprClass: case CXXOperatorCallExprClass: case CXXMemberCallExprClass: @@ -3254,11 +3292,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case LambdaExprClass: { const LambdaExpr *LE = cast<LambdaExpr>(this); - for (LambdaExpr::capture_iterator I = LE->capture_begin(), - E = LE->capture_end(); I != E; ++I) - if (I->getCaptureKind() == LCK_ByCopy) - // FIXME: Only has a side-effect if the variable is volatile or if - // the copy would invoke a non-trivial copy constructor. + for (Expr *E : LE->capture_inits()) + if (E->HasSideEffects(Ctx, IncludePossibleEffects)) return true; return false; } @@ -3389,20 +3424,20 @@ Expr::isNullPointerConstant(ASTContext &Ctx, // Check that it is a cast to void*. if (const PointerType *PT = CE->getType()->getAs<PointerType>()) { QualType Pointee = PT->getPointeeType(); + Qualifiers Qs = Pointee.getQualifiers(); // Only (void*)0 or equivalent are treated as nullptr. If pointee type // has non-default address space it is not treated as nullptr. // (__generic void*)0 in OpenCL 2.0 should not be treated as nullptr // since it cannot be assigned to a pointer to constant address space. - bool PointeeHasDefaultAS = - Pointee.getAddressSpace() == LangAS::Default || - (Ctx.getLangOpts().OpenCLVersion >= 200 && + if ((Ctx.getLangOpts().OpenCLVersion >= 200 && Pointee.getAddressSpace() == LangAS::opencl_generic) || (Ctx.getLangOpts().OpenCL && Ctx.getLangOpts().OpenCLVersion < 200 && - Pointee.getAddressSpace() == LangAS::opencl_private); + Pointee.getAddressSpace() == LangAS::opencl_private)) + Qs.removeAddressSpace(); - if (PointeeHasDefaultAS && Pointee->isVoidType() && // to void* - CE->getSubExpr()->getType()->isIntegerType()) // from int. + if (Pointee->isVoidType() && Qs.empty() && // to void* + CE->getSubExpr()->getType()->isIntegerType()) // from int return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC); } } @@ -3952,27 +3987,48 @@ SourceLocation DesignatedInitUpdateExpr::getEndLoc() const { return getBase()->getEndLoc(); } -ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc, - ArrayRef<Expr*> exprs, - SourceLocation rparenloc) - : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, - false, false, false, false), - NumExprs(exprs.size()), LParenLoc(lparenloc), RParenLoc(rparenloc) { - Exprs = new (C) Stmt*[exprs.size()]; - for (unsigned i = 0; i != exprs.size(); ++i) { - if (exprs[i]->isTypeDependent()) +ParenListExpr::ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs, + SourceLocation RParenLoc) + : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, + false, false), + LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + ParenListExprBits.NumExprs = Exprs.size(); + + for (unsigned I = 0, N = Exprs.size(); I != N; ++I) { + if (Exprs[I]->isTypeDependent()) ExprBits.TypeDependent = true; - if (exprs[i]->isValueDependent()) + if (Exprs[I]->isValueDependent()) ExprBits.ValueDependent = true; - if (exprs[i]->isInstantiationDependent()) + if (Exprs[I]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (exprs[i]->containsUnexpandedParameterPack()) + if (Exprs[I]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - Exprs[i] = exprs[i]; + getTrailingObjects<Stmt *>()[I] = Exprs[I]; } } +ParenListExpr::ParenListExpr(EmptyShell Empty, unsigned NumExprs) + : Expr(ParenListExprClass, Empty) { + ParenListExprBits.NumExprs = NumExprs; +} + +ParenListExpr *ParenListExpr::Create(const ASTContext &Ctx, + SourceLocation LParenLoc, + ArrayRef<Expr *> Exprs, + SourceLocation RParenLoc) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(Exprs.size()), + alignof(ParenListExpr)); + return new (Mem) ParenListExpr(LParenLoc, Exprs, RParenLoc); +} + +ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx, + unsigned NumExprs) { + void *Mem = + Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumExprs), alignof(ParenListExpr)); + return new (Mem) ParenListExpr(EmptyShell(), NumExprs); +} + const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e)) e = ewc->getSubExpr(); diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index f14f5a361b..5ed4ea2ab7 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -749,14 +749,15 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const { return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier(); } -CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, - FieldDecl *Field, QualType T) - : Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C), - T->isLValueReferenceType() ? VK_LValue : T->isRValueReferenceType() +CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc, + FieldDecl *Field, QualType Ty) + : Expr(CXXDefaultInitExprClass, Ty.getNonLValueExprType(Ctx), + Ty->isLValueReferenceType() ? VK_LValue : Ty->isRValueReferenceType() ? VK_XValue : VK_RValue, /*FIXME*/ OK_Ordinary, false, false, false, false), - Field(Field), Loc(Loc) { + Field(Field) { + CXXDefaultInitExprBits.Loc = Loc; assert(Field->hasInClassInitializer()); } @@ -1044,12 +1045,7 @@ bool LambdaExpr::isMutable() const { ExprWithCleanups::ExprWithCleanups(Expr *subexpr, bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) - : Expr(ExprWithCleanupsClass, subexpr->getType(), - subexpr->getValueKind(), subexpr->getObjectKind(), - subexpr->isTypeDependent(), subexpr->isValueDependent(), - subexpr->isInstantiationDependent(), - subexpr->containsUnexpandedParameterPack()), - SubExpr(subexpr) { + : FullExpr(ExprWithCleanupsClass, subexpr) { ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects; ExprWithCleanupsBits.NumObjects = objects.size(); for (unsigned i = 0, e = objects.size(); i != e; ++i) @@ -1066,7 +1062,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, } ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) - : Expr(ExprWithCleanupsClass, empty) { + : FullExpr(ExprWithCleanupsClass, empty) { ExprWithCleanupsBits.NumObjects = numObjects; } @@ -1447,5 +1443,3 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C, void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(NumArgs)); return new (Mem) TypeTraitExpr(EmptyShell()); } - -void ArrayTypeTraitExpr::anchor() {} diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index e50dd9c79d..e1d6a1c9ed 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -194,6 +194,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::DesignatedInitUpdateExprClass: return Cl::CL_PRValue; + case Expr::ConstantExprClass: + return ClassifyInternal(Ctx, cast<ConstantExpr>(E)->getSubExpr()); + // Next come the complicated cases. case Expr::SubstNonTypeTemplateParmExprClass: return ClassifyInternal(Ctx, diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index a34940e53a..837dc9c2a8 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -39,11 +39,13 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" +#include "clang/AST/OSLog.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" #include <cstring> #include <functional> @@ -143,8 +145,8 @@ namespace { // If we're doing a variable assignment from e.g. malloc(N), there will // probably be a cast of some kind. In exotic cases, we might also see a // top-level ExprWithCleanups. Ignore them either way. - if (const auto *EC = dyn_cast<ExprWithCleanups>(E)) - E = EC->getSubExpr()->IgnoreParens(); + if (const auto *FE = dyn_cast<FullExpr>(E)) + E = FE->getSubExpr()->IgnoreParens(); if (const auto *Cast = dyn_cast<CastExpr>(E)) E = Cast->getSubExpr()->IgnoreParens(); @@ -505,7 +507,7 @@ namespace { } // FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact - // on the overall stack usage of deeply-recursing constexpr evaluataions. + // on the overall stack usage of deeply-recursing constexpr evaluations. // (We should cache this map rather than recomputing it repeatedly.) // But let's try this and see how it goes; we can look into caching the map // as a later change. @@ -720,6 +722,10 @@ namespace { /// Whether or not we're currently speculatively evaluating. bool IsSpeculativelyEvaluating; + /// Whether or not we're in a context where the front end requires a + /// constant value. + bool InConstantContext; + enum EvaluationMode { /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. @@ -759,18 +765,6 @@ namespace { /// context we try to fold them immediately since the optimizer never /// gets a chance to look at it. EM_PotentialConstantExpressionUnevaluated, - - /// Evaluate as a constant expression. In certain scenarios, if: - /// - we find a MemberExpr with a base that can't be evaluated, or - /// - we find a variable initialized with a call to a function that has - /// the alloc_size attribute on it - /// then we may consider evaluation to have succeeded. - /// - /// In either case, the LValue returned shall have an invalid base; in the - /// former, the base will be the invalid MemberExpr, in the latter, the - /// base will be either the alloc_size CallExpr or a CastExpr wrapping - /// said CallExpr. - EM_OffsetFold, } EvalMode; /// Are we checking whether the expression is a potential constant @@ -793,7 +787,7 @@ namespace { EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false), - EvalMode(Mode) {} + InConstantContext(false), EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; @@ -874,7 +868,6 @@ namespace { case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_PotentialConstantExpressionUnevaluated: - case EM_OffsetFold: HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -966,7 +959,6 @@ namespace { case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: - case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -985,7 +977,6 @@ namespace { case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: case EM_ConstantFold: - case EM_OffsetFold: return true; case EM_PotentialConstantExpression: @@ -1021,7 +1012,6 @@ namespace { case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: - case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -1093,18 +1083,18 @@ namespace { } }; - /// RAII object used to treat the current evaluation as the correct pointer - /// offset fold for the current EvalMode - struct FoldOffsetRAII { + /// RAII object used to set the current evaluation mode to ignore + /// side-effects. + struct IgnoreSideEffectsRAII { EvalInfo &Info; EvalInfo::EvaluationMode OldMode; - explicit FoldOffsetRAII(EvalInfo &Info) + explicit IgnoreSideEffectsRAII(EvalInfo &Info) : Info(Info), OldMode(Info.EvalMode) { if (!Info.checkingPotentialConstantExpression()) - Info.EvalMode = EvalInfo::EM_OffsetFold; + Info.EvalMode = EvalInfo::EM_IgnoreSideEffects; } - ~FoldOffsetRAII() { Info.EvalMode = OldMode; } + ~IgnoreSideEffectsRAII() { Info.EvalMode = OldMode; } }; /// RAII object used to optionally suppress diagnostics and side-effects from @@ -1300,6 +1290,14 @@ void EvalInfo::addCallStack(unsigned Limit) { } } +/// Kinds of access we can perform on an object, for diagnostics. +enum AccessKinds { + AK_Read, + AK_Assign, + AK_Increment, + AK_Decrement +}; + namespace { struct ComplexValue { private: @@ -1405,21 +1403,36 @@ namespace { set(B, true); } + private: // Check that this LValue is not based on a null pointer. If it is, produce // a diagnostic and mark the designator as invalid. - bool checkNullPointer(EvalInfo &Info, const Expr *E, - CheckSubobjectKind CSK) { + template <typename GenDiagType> + bool checkNullPointerDiagnosingWith(const GenDiagType &GenDiag) { if (Designator.Invalid) return false; if (IsNullPtr) { - Info.CCEDiag(E, diag::note_constexpr_null_subobject) - << CSK; + GenDiag(); Designator.setInvalid(); return false; } return true; } + public: + bool checkNullPointer(EvalInfo &Info, const Expr *E, + CheckSubobjectKind CSK) { + return checkNullPointerDiagnosingWith([&Info, E, CSK] { + Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; + }); + } + + bool checkNullPointerForFoldAccess(EvalInfo &Info, const Expr *E, + AccessKinds AK) { + return checkNullPointerDiagnosingWith([&Info, E, AK] { + Info.FFDiag(E, diag::note_constexpr_access_null) << AK; + }); + } + // Check this LValue refers to an object. If not, set the designator to be // invalid and emit a diagnostic. bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { @@ -2089,11 +2102,12 @@ static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E, QualType DestType, QualType SrcType, const APSInt &Value) { unsigned DestWidth = Info.Ctx.getIntWidth(DestType); - APSInt Result = Value; // Figure out if this is a truncate, extend or noop cast. // If the input is signed, do a sign extend, noop, or truncate. - Result = Result.extOrTrunc(DestWidth); + APSInt Result = Value.extOrTrunc(DestWidth); Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType()); + if (DestType->isBooleanType()) + Result = Value.getBoolValue(); return Result; } @@ -2755,14 +2769,6 @@ static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E, return false; } -/// Kinds of access we can perform on an object, for diagnostics. -enum AccessKinds { - AK_Read, - AK_Assign, - AK_Increment, - AK_Decrement -}; - namespace { /// A handle to a complete object (an object that is not a subobject of /// another object). @@ -4288,6 +4294,9 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: return EvaluateStmt(Result, Info, cast<SwitchCase>(S)->getSubStmt(), Case); + case Stmt::CXXTryStmtClass: + // Evaluate try blocks by evaluating all sub statements. + return EvaluateStmt(Result, Info, cast<CXXTryStmt>(S)->getTryBlock(), Case); } } @@ -4330,10 +4339,13 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, Declaration->isConstexpr()) return false; - // Bail out with no diagnostic if the function declaration itself is invalid. - // We will have produced a relevant diagnostic while parsing it. - if (Declaration->isInvalidDecl()) + // Bail out if the function declaration itself is invalid. We will + // have produced a relevant diagnostic while parsing it, so just + // note the problematic sub-expression. + if (Declaration->isInvalidDecl()) { + Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr); return false; + } // Can we evaluate this function call? if (Definition && Definition->isConstexpr() && @@ -4731,6 +4743,8 @@ public: return Error(E); } + bool VisitConstantExpr(const ConstantExpr *E) + { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitParenExpr(const ParenExpr *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitUnaryExtension(const UnaryOperator *E) @@ -5634,8 +5648,10 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, return false; auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) { - if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects)) + Expr::EvalResult ExprResult; + if (!E->EvaluateAsInt(ExprResult, Ctx, Expr::SE_AllowSideEffects)) return false; + Into = ExprResult.Val.getInt(); if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) return false; Into = Into.zextOrSelf(BitsInSizeT); @@ -5861,11 +5877,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { // permitted in constant expressions in C++11. Bitcasts from cv void* are // also static_casts, but we disallow them as a resolution to DR1312. if (!E->getType()->isVoidPointerType()) { - // If we changed anything other than cvr-qualifiers, we can't use this - // value for constant folding. FIXME: Qualification conversions should - // always be CK_NoOp, but we get this wrong in C. - if (!Info.Ctx.hasCvrSimilarType(E->getType(), E->getSubExpr()->getType())) - Result.Designator.setInvalid(); + Result.Designator.setInvalid(); if (SubExpr->getType()->isVoidPointerType()) CCEDiag(E, diag::note_constexpr_invalid_cast) << 3 << SubExpr->getType(); @@ -5963,21 +5975,35 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { return ExprEvaluatorBaseTy::VisitCastExpr(E); } -static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) { +static CharUnits GetAlignOfType(EvalInfo &Info, QualType T, + UnaryExprOrTypeTrait ExprKind) { // C++ [expr.alignof]p3: // When alignof is applied to a reference type, the result is the // alignment of the referenced type. if (const ReferenceType *Ref = T->getAs<ReferenceType>()) T = Ref->getPointeeType(); - // __alignof is defined to return the preferred alignment. if (T.getQualifiers().hasUnaligned()) return CharUnits::One(); - return Info.Ctx.toCharUnitsFromBits( - Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); + + const bool AlignOfReturnsPreferred = + Info.Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; + + // __alignof is defined to return the preferred alignment. + // Before 8, clang returned the preferred alignment for alignof and _Alignof + // as well. + if (ExprKind == UETT_PreferredAlignOf || AlignOfReturnsPreferred) + return Info.Ctx.toCharUnitsFromBits( + Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); + // alignof and _Alignof are defined to return the ABI alignment. + else if (ExprKind == UETT_AlignOf) + return Info.Ctx.getTypeAlignInChars(T.getTypePtr()); + else + llvm_unreachable("GetAlignOfType on a non-alignment ExprKind"); } -static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { +static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E, + UnaryExprOrTypeTrait ExprKind) { E = E->IgnoreParens(); // The kinds of expressions that we have special-case logic here for @@ -5994,7 +6020,7 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { return Info.Ctx.getDeclAlign(ME->getMemberDecl(), /*RefAsPointee*/true); - return GetAlignOfType(Info, E->getType()); + return GetAlignOfType(Info, E->getType(), ExprKind); } // To be clear: this happily visits unsupported builtins. Better name welcomed. @@ -6055,8 +6081,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, OffsetResult.Base.dyn_cast<const ValueDecl*>()) { BaseAlignment = Info.Ctx.getDeclAlign(VD); } else { - BaseAlignment = - GetAlignOfExpr(Info, OffsetResult.Base.get<const Expr*>()); + BaseAlignment = GetAlignOfExpr( + Info, OffsetResult.Base.get<const Expr *>(), UETT_AlignOf); } if (BaseAlignment < Align) { @@ -6086,7 +6112,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return true; } - + case Builtin::BI__builtin_launder: + return evaluatePointer(E->getArg(0), Result); case Builtin::BIstrchr: case Builtin::BIwcschr: case Builtin::BImemchr: @@ -6118,9 +6145,27 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return false; MaxLength = N.getExtValue(); } - - QualType CharTy = E->getArg(0)->getType()->getPointeeType(); - + // We cannot find the value if there are no candidates to match against. + if (MaxLength == 0u) + return ZeroInitialization(E); + if (!Result.checkNullPointerForFoldAccess(Info, E, AK_Read) || + Result.Designator.Invalid) + return false; + QualType CharTy = Result.Designator.getType(Info.Ctx); + bool IsRawByte = BuiltinOp == Builtin::BImemchr || + BuiltinOp == Builtin::BI__builtin_memchr; + assert(IsRawByte || + Info.Ctx.hasSameUnqualifiedType( + CharTy, E->getArg(0)->getType()->getPointeeType())); + // Pointers to const void may point to objects of incomplete type. + if (IsRawByte && CharTy->isIncompleteType()) { + Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy; + return false; + } + // Give up on byte-oriented matching against multibyte elements. + // FIXME: We can compare the bytes in the correct order. + if (IsRawByte && Info.Ctx.getTypeSizeInChars(CharTy) != CharUnits::One()) + return false; // Figure out what value we're actually looking for (after converting to // the corresponding unsigned type if necessary). uint64_t DesiredVal; @@ -6239,6 +6284,10 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, Info.FFDiag(E, diag::note_constexpr_memcpy_type_pun) << Move << SrcT << T; return false; } + if (T->isIncompleteType()) { + Info.FFDiag(E, diag::note_constexpr_memcpy_incomplete_type) << Move << T; + return false; + } if (!T.isTriviallyCopyableType(Info.Ctx)) { Info.FFDiag(E, diag::note_constexpr_memcpy_nontrivial) << Move << T; return false; @@ -7343,6 +7392,8 @@ public: // Visitor Methods //===--------------------------------------------------------------------===// + bool VisitConstantExpr(const ConstantExpr *E); + bool VisitIntegerLiteral(const IntegerLiteral *E) { return Success(E->getValue(), E); } @@ -7642,6 +7693,9 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: @@ -8046,7 +8100,7 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, // If there are any, but we can determine the pointed-to object anyway, then // ignore the side-effects. SpeculativeEvaluationRAII SpeculativeEval(Info); - FoldOffsetRAII Fold(Info); + IgnoreSideEffectsRAII Fold(Info); if (E->isGLValue()) { // It's possible for us to be given GLValues if we're called via @@ -8080,6 +8134,11 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, return true; } +bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) { + llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true); + return ExprEvaluatorBaseTy::VisitConstantExpr(E); +} + bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { if (unsigned BuiltinOp = E->getBuiltinCallee()) return VisitBuiltinCallExpr(E, BuiltinOp); @@ -8114,7 +8173,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case EvalInfo::EM_ConstantFold: case EvalInfo::EM_EvaluateForOverflow: case EvalInfo::EM_IgnoreSideEffects: - case EvalInfo::EM_OffsetFold: // Leave it to IR generation. return Error(E); case EvalInfo::EM_ConstantExpressionUnevaluated: @@ -8126,6 +8184,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, llvm_unreachable("unexpected EvalMode"); } + case Builtin::BI__builtin_os_log_format_buffer_size: { + analyze_os_log::OSLogBufferLayout Layout; + analyze_os_log::computeOSLogBufferLayout(Info.Ctx, E, Layout); + return Success(Layout.size().getQuantity(), E); + } + case Builtin::BI__builtin_bswap16: case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { @@ -8162,8 +8226,20 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(Val.countLeadingZeros(), E); } - case Builtin::BI__builtin_constant_p: - return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E); + case Builtin::BI__builtin_constant_p: { + auto Arg = E->getArg(0); + if (EvaluateBuiltinConstantP(Info.Ctx, Arg)) + return Success(true, E); + auto ArgTy = Arg->IgnoreImplicit()->getType(); + if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) && + !ArgTy->isAggregateType() && !ArgTy->isPointerType()) { + // We can delay calculation of __builtin_constant_p until after + // inlining. Note: This diagnostic won't be shown to the user. + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } + return Success(false, E); + } case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: @@ -8343,8 +8419,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, !EvaluatePointer(E->getArg(1), String2, Info)) return false; - QualType CharTy = E->getArg(0)->getType()->getPointeeType(); - uint64_t MaxLength = uint64_t(-1); if (BuiltinOp != Builtin::BIstrcmp && BuiltinOp != Builtin::BIwcscmp && @@ -8355,6 +8429,88 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return false; MaxLength = N.getExtValue(); } + + // Empty substrings compare equal by definition. + if (MaxLength == 0u) + return Success(0, E); + + if (!String1.checkNullPointerForFoldAccess(Info, E, AK_Read) || + !String2.checkNullPointerForFoldAccess(Info, E, AK_Read) || + String1.Designator.Invalid || String2.Designator.Invalid) + return false; + + QualType CharTy1 = String1.Designator.getType(Info.Ctx); + QualType CharTy2 = String2.Designator.getType(Info.Ctx); + + bool IsRawByte = BuiltinOp == Builtin::BImemcmp || + BuiltinOp == Builtin::BI__builtin_memcmp; + + assert(IsRawByte || + (Info.Ctx.hasSameUnqualifiedType( + CharTy1, E->getArg(0)->getType()->getPointeeType()) && + Info.Ctx.hasSameUnqualifiedType(CharTy1, CharTy2))); + + const auto &ReadCurElems = [&](APValue &Char1, APValue &Char2) { + return handleLValueToRValueConversion(Info, E, CharTy1, String1, Char1) && + handleLValueToRValueConversion(Info, E, CharTy2, String2, Char2) && + Char1.isInt() && Char2.isInt(); + }; + const auto &AdvanceElems = [&] { + return HandleLValueArrayAdjustment(Info, E, String1, CharTy1, 1) && + HandleLValueArrayAdjustment(Info, E, String2, CharTy2, 1); + }; + + if (IsRawByte) { + uint64_t BytesRemaining = MaxLength; + // Pointers to const void may point to objects of incomplete type. + if (CharTy1->isIncompleteType()) { + Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy1; + return false; + } + if (CharTy2->isIncompleteType()) { + Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy2; + return false; + } + uint64_t CharTy1Width{Info.Ctx.getTypeSize(CharTy1)}; + CharUnits CharTy1Size = Info.Ctx.toCharUnitsFromBits(CharTy1Width); + // Give up on comparing between elements with disparate widths. + if (CharTy1Size != Info.Ctx.getTypeSizeInChars(CharTy2)) + return false; + uint64_t BytesPerElement = CharTy1Size.getQuantity(); + assert(BytesRemaining && "BytesRemaining should not be zero: the " + "following loop considers at least one element"); + while (true) { + APValue Char1, Char2; + if (!ReadCurElems(Char1, Char2)) + return false; + // We have compatible in-memory widths, but a possible type and + // (for `bool`) internal representation mismatch. + // Assuming two's complement representation, including 0 for `false` and + // 1 for `true`, we can check an appropriate number of elements for + // equality even if they are not byte-sized. + APSInt Char1InMem = Char1.getInt().extOrTrunc(CharTy1Width); + APSInt Char2InMem = Char2.getInt().extOrTrunc(CharTy1Width); + if (Char1InMem.ne(Char2InMem)) { + // If the elements are byte-sized, then we can produce a three-way + // comparison result in a straightforward manner. + if (BytesPerElement == 1u) { + // memcmp always compares unsigned chars. + return Success(Char1InMem.ult(Char2InMem) ? -1 : 1, E); + } + // The result is byte-order sensitive, and we have multibyte elements. + // FIXME: We can compare the remaining bytes in the correct order. + return false; + } + if (!AdvanceElems()) + return false; + if (BytesRemaining <= BytesPerElement) + break; + BytesRemaining -= BytesPerElement; + } + // Enough elements are equal to account for the memcmp limit. + return Success(0, E); + } + bool StopAtNull = (BuiltinOp != Builtin::BImemcmp && BuiltinOp != Builtin::BIwmemcmp && BuiltinOp != Builtin::BI__builtin_memcmp && @@ -8365,11 +8521,10 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, BuiltinOp == Builtin::BI__builtin_wcscmp || BuiltinOp == Builtin::BI__builtin_wcsncmp || BuiltinOp == Builtin::BI__builtin_wmemcmp; + for (; MaxLength; --MaxLength) { APValue Char1, Char2; - if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) || - !handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) || - !Char1.isInt() || !Char2.isInt()) + if (!ReadCurElems(Char1, Char2)) return false; if (Char1.getInt() != Char2.getInt()) { if (IsWide) // wmemcmp compares with wchar_t signedness. @@ -8380,8 +8535,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (StopAtNull && !Char1.getInt()) return Success(0, E); assert(!(StopAtNull && !Char2.getInt())); - if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) || - !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1)) + if (!AdvanceElems()) return false; } // We hit the strncmp / memcmp limit. @@ -9372,11 +9526,14 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( const UnaryExprOrTypeTraitExpr *E) { switch(E->getKind()) { + case UETT_PreferredAlignOf: case UETT_AlignOf: { if (E->isArgumentType()) - return Success(GetAlignOfType(Info, E->getArgumentType()), E); + return Success(GetAlignOfType(Info, E->getArgumentType(), E->getKind()), + E); else - return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E); + return Success(GetAlignOfExpr(Info, E->getArgumentExpr(), E->getKind()), + E); } case UETT_VecStep: { @@ -9565,11 +9722,11 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralComplexCast: case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: - case CK_ZeroToOCLEvent: - case CK_ZeroToOCLQueue: + case CK_ZeroToOCLOpaqueType: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: + case CK_FixedPointCast: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -9604,6 +9761,14 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return Success(IntResult, E); } + case CK_FixedPointToBoolean: { + // Unsigned padding does not affect this. + APValue Val; + if (!Evaluate(Val, Info, SubExpr)) + return false; + return Success(Val.getInt().getBoolValue(), E); + } + case CK_IntegralCast: { if (!Visit(SubExpr)) return false; @@ -10099,11 +10264,12 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: - case CK_ZeroToOCLEvent: - case CK_ZeroToOCLQueue: + case CK_ZeroToOCLOpaqueType: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: + case CK_FixedPointCast: + case CK_FixedPointToBoolean: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -10264,7 +10430,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Mul: if (Result.isComplexFloat()) { // This is an implementation of complex multiplication according to the - // constraints laid out in C11 Annex G. The implemention uses the + // constraints laid out in C11 Annex G. The implementation uses the // following naming scheme: // (a + ib) * (c + id) ComplexValue LHS = Result; @@ -10345,7 +10511,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Div: if (Result.isComplexFloat()) { // This is an implementation of complex division according to the - // constraints laid out in C11 Annex G. The implemention uses the + // constraints laid out in C11 Annex G. The implementation uses the // following naming scheme: // (a + ib) / (c + id) ComplexValue LHS = Result; @@ -10721,19 +10887,46 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, return false; } +static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, + Expr::SideEffectsKind SEK) { + return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) || + (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior); +} + +static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result, + const ASTContext &Ctx, EvalInfo &Info) { + bool IsConst; + if (FastEvaluateAsRValue(E, Result, Ctx, IsConst)) + return IsConst; + + return EvaluateAsRValue(Info, E, Result.Val); +} + +static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult, + const ASTContext &Ctx, + Expr::SideEffectsKind AllowSideEffects, + EvalInfo &Info) { + if (!E->getType()->isIntegralOrEnumerationType()) + return false; + + if (!::EvaluateAsRValue(E, ExprResult, Ctx, Info) || + !ExprResult.Val.isInt() || + hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) + return false; + + return true; +} /// EvaluateAsRValue - Return true if this is a constant which we can fold using /// any crazy technique (that has nothing to do with language standards) that /// we want to. If this function returns true, it returns the folded constant /// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion /// will be applied to the result. -bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { - bool IsConst; - if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) - return IsConst; - +bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, + bool InConstantContext) const { EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); - return ::EvaluateAsRValue(Info, this, Result.Val); + Info.InConstantContext = InConstantContext; + return ::EvaluateAsRValue(this, Result, Ctx, Info); } bool Expr::EvaluateAsBooleanCondition(bool &Result, @@ -10743,24 +10936,10 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result, HandleConversionToBool(Scratch.Val, Result); } -static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, - Expr::SideEffectsKind SEK) { - return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) || - (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior); -} - -bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, +bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects) const { - if (!getType()->isIntegralOrEnumerationType()) - return false; - - EvalResult ExprResult; - if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() || - hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) - return false; - - Result = ExprResult.Val.getInt(); - return true; + EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info); } bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, @@ -10818,6 +10997,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, ? EvalInfo::EM_ConstantExpression : EvalInfo::EM_ConstantFold); InitInfo.setEvaluatingDecl(VD, Value); + InitInfo.InConstantContext = true; LValue LVal; LVal.set(VD); @@ -10847,28 +11027,46 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, /// constant folded, but discard the result. bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const { EvalResult Result; - return EvaluateAsRValue(Result, Ctx) && + return EvaluateAsRValue(Result, Ctx, /* in constant context */ true) && !hasUnacceptableSideEffect(Result, SEK); } APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const { - EvalResult EvalResult; - EvalResult.Diag = Diag; - bool Result = EvaluateAsRValue(EvalResult, Ctx); + EvalResult EVResult; + EVResult.Diag = Diag; + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + Info.InConstantContext = true; + + bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info); (void)Result; assert(Result && "Could not evaluate expression"); - assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); + assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); - return EvalResult.Val.getInt(); + return EVResult.Val.getInt(); +} + +APSInt Expr::EvaluateKnownConstIntCheckOverflow( + const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const { + EvalResult EVResult; + EVResult.Diag = Diag; + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow); + Info.InConstantContext = true; + + bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val); + (void)Result; + assert(Result && "Could not evaluate expression"); + assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); + + return EVResult.Val.getInt(); } void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; - EvalResult EvalResult; - if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { - EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); - (void)::EvaluateAsRValue(Info, this, EvalResult.Val); + EvalResult EVResult; + if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) { + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow); + (void)::EvaluateAsRValue(Info, this, EVResult.Val); } } @@ -10921,7 +11119,11 @@ static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { Expr::EvalResult EVResult; - if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + + Info.InConstantContext = true; + if (!::EvaluateAsRValue(E, EVResult, Ctx, Info) || EVResult.HasSideEffects || !EVResult.Val.isInt()) return ICEDiag(IK_NotICE, E->getBeginLoc()); @@ -11037,6 +11239,9 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx); + case Expr::ConstantExprClass: + return CheckICE(cast<ConstantExpr>(E)->getSubExpr(), Ctx); + case Expr::ParenExprClass: return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx); case Expr::GenericSelectionExprClass: @@ -11115,9 +11320,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case UO_Imag: return CheckICE(Exp->getSubExpr(), Ctx); } - - // OffsetOf falls through here. - LLVM_FALLTHROUGH; + llvm_unreachable("invalid unary operator class"); } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using @@ -11221,7 +11424,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return Worst(LHSResult, RHSResult); } } - LLVM_FALLTHROUGH; + llvm_unreachable("invalid binary operator kind"); } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: @@ -11358,12 +11561,20 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, if (!isIntegerConstantExpr(Ctx, Loc)) return false; + // The only possible side-effects here are due to UB discovered in the // evaluation (for instance, INT_MAX + 1). In such a case, we are still // required to treat the expression as an ICE, so we produce the folded // value. - if (!EvaluateAsInt(Value, Ctx, SE_AllowSideEffects)) + EvalResult ExprResult; + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects); + Info.InConstantContext = true; + + if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info)) llvm_unreachable("ICE cannot be evaluated!"); + + Value = ExprResult.Val.getInt(); return true; } @@ -11449,6 +11660,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_PotentialConstantExpression); + Info.InConstantContext = true; const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr; diff --git a/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp index ae28c588ca..12e6bfc041 100644 --- a/lib/AST/ExternalASTMerger.cpp +++ b/lib/AST/ExternalASTMerger.cpp @@ -144,14 +144,14 @@ public: } if (auto *ToTag = dyn_cast<TagDecl>(To)) { ToTag->setHasExternalLexicalStorage(); - ToTag->setMustBuildLookupTable(); + ToTag->getPrimaryContext()->setMustBuildLookupTable(); assert(Parent.CanComplete(ToTag)); } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) { ToNamespace->setHasExternalVisibleStorage(); assert(Parent.CanComplete(ToNamespace)); } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) { ToContainer->setHasExternalLexicalStorage(); - ToContainer->setMustBuildLookupTable(); + ToContainer->getPrimaryContext()->setMustBuildLookupTable(); assert(Parent.CanComplete(ToContainer)); } return To; @@ -230,7 +230,8 @@ void ExternalASTMerger::CompleteType(TagDecl *Tag) { if (!SourceTag->getDefinition()) return false; Forward.MapImported(SourceTag, Tag); - Forward.ImportDefinition(SourceTag); + if (llvm::Error Err = Forward.ImportDefinition_New(SourceTag)) + llvm::consumeError(std::move(Err)); Tag->setCompleteDefinition(SourceTag->isCompleteDefinition()); return true; }); @@ -249,7 +250,8 @@ void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) { if (!SourceInterface->getDefinition()) return false; Forward.MapImported(SourceInterface, Interface); - Forward.ImportDefinition(SourceInterface); + if (llvm::Error Err = Forward.ImportDefinition_New(SourceInterface)) + llvm::consumeError(std::move(Err)); return true; }); } diff --git a/lib/AST/FormatString.cpp b/lib/AST/FormatString.cpp new file mode 100644 index 0000000000..04bd48f14a --- /dev/null +++ b/lib/AST/FormatString.cpp @@ -0,0 +1,993 @@ +// FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Shared details for processing format strings of printf and scanf +// (and friends). +// +//===----------------------------------------------------------------------===// + +#include "FormatStringParsing.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/Support/ConvertUTF.h" + +using clang::analyze_format_string::ArgType; +using clang::analyze_format_string::FormatStringHandler; +using clang::analyze_format_string::FormatSpecifier; +using clang::analyze_format_string::LengthModifier; +using clang::analyze_format_string::OptionalAmount; +using clang::analyze_format_string::PositionContext; +using clang::analyze_format_string::ConversionSpecifier; +using namespace clang; + +// Key function to FormatStringHandler. +FormatStringHandler::~FormatStringHandler() {} + +//===----------------------------------------------------------------------===// +// Functions for parsing format strings components in both printf and +// scanf format strings. +//===----------------------------------------------------------------------===// + +OptionalAmount +clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) { + const char *I = Beg; + UpdateOnReturn <const char*> UpdateBeg(Beg, I); + + unsigned accumulator = 0; + bool hasDigits = false; + + for ( ; I != E; ++I) { + char c = *I; + if (c >= '0' && c <= '9') { + hasDigits = true; + accumulator = (accumulator * 10) + (c - '0'); + continue; + } + + if (hasDigits) + return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg, + false); + + break; + } + + return OptionalAmount(); +} + +OptionalAmount +clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg, + const char *E, + unsigned &argIndex) { + if (*Beg == '*') { + ++Beg; + return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false); + } + + return ParseAmount(Beg, E); +} + +OptionalAmount +clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H, + const char *Start, + const char *&Beg, + const char *E, + PositionContext p) { + if (*Beg == '*') { + const char *I = Beg + 1; + const OptionalAmount &Amt = ParseAmount(I, E); + + if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) { + H.HandleInvalidPosition(Beg, I - Beg, p); + return OptionalAmount(false); + } + + if (I == E) { + // No more characters left? + H.HandleIncompleteSpecifier(Start, E - Start); + return OptionalAmount(false); + } + + assert(Amt.getHowSpecified() == OptionalAmount::Constant); + + if (*I == '$') { + // Handle positional arguments + + // Special case: '*0$', since this is an easy mistake. + if (Amt.getConstantAmount() == 0) { + H.HandleZeroPosition(Beg, I - Beg + 1); + return OptionalAmount(false); + } + + const char *Tmp = Beg; + Beg = ++I; + + return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1, + Tmp, 0, true); + } + + H.HandleInvalidPosition(Beg, I - Beg, p); + return OptionalAmount(false); + } + + return ParseAmount(Beg, E); +} + + +bool +clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H, + FormatSpecifier &CS, + const char *Start, + const char *&Beg, const char *E, + unsigned *argIndex) { + // FIXME: Support negative field widths. + if (argIndex) { + CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); + } + else { + const OptionalAmount Amt = + ParsePositionAmount(H, Start, Beg, E, + analyze_format_string::FieldWidthPos); + + if (Amt.isInvalid()) + return true; + CS.setFieldWidth(Amt); + } + return false; +} + +bool +clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H, + FormatSpecifier &FS, + const char *Start, + const char *&Beg, + const char *E) { + const char *I = Beg; + + const OptionalAmount &Amt = ParseAmount(I, E); + + if (I == E) { + // No more characters left? + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') { + // Warn that positional arguments are non-standard. + H.HandlePosition(Start, I - Start); + + // Special case: '%0$', since this is an easy mistake. + if (Amt.getConstantAmount() == 0) { + H.HandleZeroPosition(Start, I - Start); + return true; + } + + FS.setArgIndex(Amt.getConstantAmount() - 1); + FS.setUsesPositionalArg(); + // Update the caller's pointer if we decided to consume + // these characters. + Beg = I; + return false; + } + + return false; +} + +bool +clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H, + FormatSpecifier &FS, + const char *&I, + const char *E, + const LangOptions &LO) { + if (!LO.OpenCL) + return false; + + const char *Start = I; + if (*I == 'v') { + ++I; + + if (I == E) { + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + OptionalAmount NumElts = ParseAmount(I, E); + if (NumElts.getHowSpecified() != OptionalAmount::Constant) { + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + FS.setVectorNumElts(NumElts); + } + + return false; +} + +bool +clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, + const char *&I, + const char *E, + const LangOptions &LO, + bool IsScanf) { + LengthModifier::Kind lmKind = LengthModifier::None; + const char *lmPosition = I; + switch (*I) { + default: + return false; + case 'h': + ++I; + if (I != E && *I == 'h') { + ++I; + lmKind = LengthModifier::AsChar; + } else { + lmKind = LengthModifier::AsShort; + } + break; + case 'l': + ++I; + if (I != E && *I == 'l') { + ++I; + lmKind = LengthModifier::AsLongLong; + } else { + lmKind = LengthModifier::AsLong; + } + break; + case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; + case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; + case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; + case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; + case 'q': lmKind = LengthModifier::AsQuad; ++I; break; + case 'a': + if (IsScanf && !LO.C99 && !LO.CPlusPlus11) { + // For scanf in C90, look at the next character to see if this should + // be parsed as the GNU extension 'a' length modifier. If not, this + // will be parsed as a conversion specifier. + ++I; + if (I != E && (*I == 's' || *I == 'S' || *I == '[')) { + lmKind = LengthModifier::AsAllocate; + break; + } + --I; + } + return false; + case 'm': + if (IsScanf) { + lmKind = LengthModifier::AsMAllocate; + ++I; + break; + } + return false; + // printf: AsInt64, AsInt32, AsInt3264 + // scanf: AsInt64 + case 'I': + if (I + 1 != E && I + 2 != E) { + if (I[1] == '6' && I[2] == '4') { + I += 3; + lmKind = LengthModifier::AsInt64; + break; + } + if (IsScanf) + return false; + + if (I[1] == '3' && I[2] == '2') { + I += 3; + lmKind = LengthModifier::AsInt32; + break; + } + } + ++I; + lmKind = LengthModifier::AsInt3264; + break; + case 'w': + lmKind = LengthModifier::AsWide; ++I; break; + } + LengthModifier lm(lmPosition, lmKind); + FS.setLengthModifier(lm); + return true; +} + +bool clang::analyze_format_string::ParseUTF8InvalidSpecifier( + const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) { + if (SpecifierBegin + 1 >= FmtStrEnd) + return false; + + const llvm::UTF8 *SB = + reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1); + const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd); + const char FirstByte = *SB; + + // If the invalid specifier is a multibyte UTF-8 string, return the + // total length accordingly so that the conversion specifier can be + // properly updated to reflect a complete UTF-8 specifier. + unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte); + if (NumBytes == 1) + return false; + if (SB + NumBytes > SE) + return false; + + Len = NumBytes + 1; + return true; +} + +//===----------------------------------------------------------------------===// +// Methods on ArgType. +//===----------------------------------------------------------------------===// + +clang::analyze_format_string::ArgType::MatchKind +ArgType::matchesType(ASTContext &C, QualType argTy) const { + if (Ptr) { + // It has to be a pointer. + const PointerType *PT = argTy->getAs<PointerType>(); + if (!PT) + return NoMatch; + + // We cannot write through a const qualified pointer. + if (PT->getPointeeType().isConstQualified()) + return NoMatch; + + argTy = PT->getPointeeType(); + } + + switch (K) { + case InvalidTy: + llvm_unreachable("ArgType must be valid"); + + case UnknownTy: + return Match; + + case AnyCharTy: { + if (const EnumType *ETy = argTy->getAs<EnumType>()) { + // If the enum is incomplete we know nothing about the underlying type. + // Assume that it's 'int'. + if (!ETy->getDecl()->isComplete()) + return NoMatch; + argTy = ETy->getDecl()->getIntegerType(); + } + + if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) + switch (BT->getKind()) { + default: + break; + case BuiltinType::Char_S: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::Char_U: + return Match; + } + return NoMatch; + } + + case SpecificTy: { + if (const EnumType *ETy = argTy->getAs<EnumType>()) { + // If the enum is incomplete we know nothing about the underlying type. + // Assume that it's 'int'. + if (!ETy->getDecl()->isComplete()) + argTy = C.IntTy; + else + argTy = ETy->getDecl()->getIntegerType(); + } + argTy = C.getCanonicalType(argTy).getUnqualifiedType(); + + if (T == argTy) + return Match; + // Check for "compatible types". + if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) + switch (BT->getKind()) { + default: + break; + case BuiltinType::Char_S: + case BuiltinType::SChar: + case BuiltinType::Char_U: + case BuiltinType::UChar: + return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match + : NoMatch; + case BuiltinType::Short: + return T == C.UnsignedShortTy ? Match : NoMatch; + case BuiltinType::UShort: + return T == C.ShortTy ? Match : NoMatch; + case BuiltinType::Int: + return T == C.UnsignedIntTy ? Match : NoMatch; + case BuiltinType::UInt: + return T == C.IntTy ? Match : NoMatch; + case BuiltinType::Long: + return T == C.UnsignedLongTy ? Match : NoMatch; + case BuiltinType::ULong: + return T == C.LongTy ? Match : NoMatch; + case BuiltinType::LongLong: + return T == C.UnsignedLongLongTy ? Match : NoMatch; + case BuiltinType::ULongLong: + return T == C.LongLongTy ? Match : NoMatch; + } + return NoMatch; + } + + case CStrTy: { + const PointerType *PT = argTy->getAs<PointerType>(); + if (!PT) + return NoMatch; + QualType pointeeTy = PT->getPointeeType(); + if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) + switch (BT->getKind()) { + case BuiltinType::Void: + case BuiltinType::Char_U: + case BuiltinType::UChar: + case BuiltinType::Char_S: + case BuiltinType::SChar: + return Match; + default: + break; + } + + return NoMatch; + } + + case WCStrTy: { + const PointerType *PT = argTy->getAs<PointerType>(); + if (!PT) + return NoMatch; + QualType pointeeTy = + C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); + return pointeeTy == C.getWideCharType() ? Match : NoMatch; + } + + case WIntTy: { + QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); + + if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt) + return Match; + + QualType PromoArg = argTy->isPromotableIntegerType() + ? C.getPromotedIntegerType(argTy) + : argTy; + PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); + + // If the promoted argument is the corresponding signed type of the + // wint_t type, then it should match. + if (PromoArg->hasSignedIntegerRepresentation() && + C.getCorrespondingUnsignedType(PromoArg) == WInt) + return Match; + + return WInt == PromoArg ? Match : NoMatch; + } + + case CPointerTy: + if (argTy->isVoidPointerType()) { + return Match; + } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() || + argTy->isBlockPointerType() || argTy->isNullPtrType()) { + return NoMatchPedantic; + } else { + return NoMatch; + } + + case ObjCPointerTy: { + if (argTy->getAs<ObjCObjectPointerType>() || + argTy->getAs<BlockPointerType>()) + return Match; + + // Handle implicit toll-free bridging. + if (const PointerType *PT = argTy->getAs<PointerType>()) { + // Things such as CFTypeRef are really just opaque pointers + // to C structs representing CF types that can often be bridged + // to Objective-C objects. Since the compiler doesn't know which + // structs can be toll-free bridged, we just accept them all. + QualType pointee = PT->getPointeeType(); + if (pointee->getAsStructureType() || pointee->isVoidType()) + return Match; + } + return NoMatch; + } + } + + llvm_unreachable("Invalid ArgType Kind!"); +} + +ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const { + if (K != SpecificTy) // Won't be a valid vector element type. + return ArgType::Invalid(); + + QualType Vec = C.getExtVectorType(T, NumElts); + return ArgType(Vec, Name); +} + +QualType ArgType::getRepresentativeType(ASTContext &C) const { + QualType Res; + switch (K) { + case InvalidTy: + llvm_unreachable("No representative type for Invalid ArgType"); + case UnknownTy: + llvm_unreachable("No representative type for Unknown ArgType"); + case AnyCharTy: + Res = C.CharTy; + break; + case SpecificTy: + Res = T; + break; + case CStrTy: + Res = C.getPointerType(C.CharTy); + break; + case WCStrTy: + Res = C.getPointerType(C.getWideCharType()); + break; + case ObjCPointerTy: + Res = C.ObjCBuiltinIdTy; + break; + case CPointerTy: + Res = C.VoidPtrTy; + break; + case WIntTy: { + Res = C.getWIntType(); + break; + } + } + + if (Ptr) + Res = C.getPointerType(Res); + return Res; +} + +std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { + std::string S = getRepresentativeType(C).getAsString(); + + std::string Alias; + if (Name) { + // Use a specific name for this type, e.g. "size_t". + Alias = Name; + if (Ptr) { + // If ArgType is actually a pointer to T, append an asterisk. + Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *"; + } + // If Alias is the same as the underlying type, e.g. wchar_t, then drop it. + if (S == Alias) + Alias.clear(); + } + + if (!Alias.empty()) + return std::string("'") + Alias + "' (aka '" + S + "')"; + return std::string("'") + S + "'"; +} + + +//===----------------------------------------------------------------------===// +// Methods on OptionalAmount. +//===----------------------------------------------------------------------===// + +ArgType +analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const { + return Ctx.IntTy; +} + +//===----------------------------------------------------------------------===// +// Methods on LengthModifier. +//===----------------------------------------------------------------------===// + +const char * +analyze_format_string::LengthModifier::toString() const { + switch (kind) { + case AsChar: + return "hh"; + case AsShort: + return "h"; + case AsLong: // or AsWideChar + return "l"; + case AsLongLong: + return "ll"; + case AsQuad: + return "q"; + case AsIntMax: + return "j"; + case AsSizeT: + return "z"; + case AsPtrDiff: + return "t"; + case AsInt32: + return "I32"; + case AsInt3264: + return "I"; + case AsInt64: + return "I64"; + case AsLongDouble: + return "L"; + case AsAllocate: + return "a"; + case AsMAllocate: + return "m"; + case AsWide: + return "w"; + case None: + return ""; + } + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Methods on ConversionSpecifier. +//===----------------------------------------------------------------------===// + +const char *ConversionSpecifier::toString() const { + switch (kind) { + case dArg: return "d"; + case DArg: return "D"; + case iArg: return "i"; + case oArg: return "o"; + case OArg: return "O"; + case uArg: return "u"; + case UArg: return "U"; + case xArg: return "x"; + case XArg: return "X"; + case fArg: return "f"; + case FArg: return "F"; + case eArg: return "e"; + case EArg: return "E"; + case gArg: return "g"; + case GArg: return "G"; + case aArg: return "a"; + case AArg: return "A"; + case cArg: return "c"; + case sArg: return "s"; + case pArg: return "p"; + case PArg: + return "P"; + case nArg: return "n"; + case PercentArg: return "%"; + case ScanListArg: return "["; + case InvalidSpecifier: return nullptr; + + // POSIX unicode extensions. + case CArg: return "C"; + case SArg: return "S"; + + // Objective-C specific specifiers. + case ObjCObjArg: return "@"; + + // FreeBSD kernel specific specifiers. + case FreeBSDbArg: return "b"; + case FreeBSDDArg: return "D"; + case FreeBSDrArg: return "r"; + case FreeBSDyArg: return "y"; + + // GlibC specific specifiers. + case PrintErrno: return "m"; + + // MS specific specifiers. + case ZArg: return "Z"; + } + return nullptr; +} + +Optional<ConversionSpecifier> +ConversionSpecifier::getStandardSpecifier() const { + ConversionSpecifier::Kind NewKind; + + switch (getKind()) { + default: + return None; + case DArg: + NewKind = dArg; + break; + case UArg: + NewKind = uArg; + break; + case OArg: + NewKind = oArg; + break; + } + + ConversionSpecifier FixedCS(*this); + FixedCS.setKind(NewKind); + return FixedCS; +} + +//===----------------------------------------------------------------------===// +// Methods on OptionalAmount. +//===----------------------------------------------------------------------===// + +void OptionalAmount::toString(raw_ostream &os) const { + switch (hs) { + case Invalid: + case NotSpecified: + return; + case Arg: + if (UsesDotPrefix) + os << "."; + if (usesPositionalArg()) + os << "*" << getPositionalArgIndex() << "$"; + else + os << "*"; + break; + case Constant: + if (UsesDotPrefix) + os << "."; + os << amt; + break; + } +} + +bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { + switch (LM.getKind()) { + case LengthModifier::None: + return true; + + // Handle most integer flags + case LengthModifier::AsShort: + if (Target.getTriple().isOSMSVCRT()) { + switch (CS.getKind()) { + case ConversionSpecifier::cArg: + case ConversionSpecifier::CArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::SArg: + case ConversionSpecifier::ZArg: + return true; + default: + break; + } + } + LLVM_FALLTHROUGH; + case LengthModifier::AsChar: + case LengthModifier::AsLongLong: + case LengthModifier::AsQuad: + case LengthModifier::AsIntMax: + case LengthModifier::AsSizeT: + case LengthModifier::AsPtrDiff: + switch (CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::OArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::UArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + case ConversionSpecifier::nArg: + return true; + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); + default: + return false; + } + + // Handle 'l' flag + case LengthModifier::AsLong: // or AsWideChar + switch (CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::OArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::UArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + case ConversionSpecifier::nArg: + case ConversionSpecifier::cArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::ScanListArg: + case ConversionSpecifier::ZArg: + return true; + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); + default: + return false; + } + + case LengthModifier::AsLongDouble: + switch (CS.getKind()) { + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + return true; + // GNU libc extension. + case ConversionSpecifier::dArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + return !Target.getTriple().isOSDarwin() && + !Target.getTriple().isOSWindows(); + default: + return false; + } + + case LengthModifier::AsAllocate: + switch (CS.getKind()) { + case ConversionSpecifier::sArg: + case ConversionSpecifier::SArg: + case ConversionSpecifier::ScanListArg: + return true; + default: + return false; + } + + case LengthModifier::AsMAllocate: + switch (CS.getKind()) { + case ConversionSpecifier::cArg: + case ConversionSpecifier::CArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::SArg: + case ConversionSpecifier::ScanListArg: + return true; + default: + return false; + } + case LengthModifier::AsInt32: + case LengthModifier::AsInt3264: + case LengthModifier::AsInt64: + switch (CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + return Target.getTriple().isOSMSVCRT(); + default: + return false; + } + case LengthModifier::AsWide: + switch (CS.getKind()) { + case ConversionSpecifier::cArg: + case ConversionSpecifier::CArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::SArg: + case ConversionSpecifier::ZArg: + return Target.getTriple().isOSMSVCRT(); + default: + return false; + } + } + llvm_unreachable("Invalid LengthModifier Kind!"); +} + +bool FormatSpecifier::hasStandardLengthModifier() const { + switch (LM.getKind()) { + case LengthModifier::None: + case LengthModifier::AsChar: + case LengthModifier::AsShort: + case LengthModifier::AsLong: + case LengthModifier::AsLongLong: + case LengthModifier::AsIntMax: + case LengthModifier::AsSizeT: + case LengthModifier::AsPtrDiff: + case LengthModifier::AsLongDouble: + return true; + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + case LengthModifier::AsQuad: + case LengthModifier::AsInt32: + case LengthModifier::AsInt3264: + case LengthModifier::AsInt64: + case LengthModifier::AsWide: + return false; + } + llvm_unreachable("Invalid LengthModifier Kind!"); +} + +bool FormatSpecifier::hasStandardConversionSpecifier( + const LangOptions &LangOpt) const { + switch (CS.getKind()) { + case ConversionSpecifier::cArg: + case ConversionSpecifier::dArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::pArg: + case ConversionSpecifier::nArg: + case ConversionSpecifier::ObjCObjArg: + case ConversionSpecifier::ScanListArg: + case ConversionSpecifier::PercentArg: + case ConversionSpecifier::PArg: + return true; + case ConversionSpecifier::CArg: + case ConversionSpecifier::SArg: + return LangOpt.ObjC; + case ConversionSpecifier::InvalidSpecifier: + case ConversionSpecifier::FreeBSDbArg: + case ConversionSpecifier::FreeBSDDArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + case ConversionSpecifier::PrintErrno: + case ConversionSpecifier::DArg: + case ConversionSpecifier::OArg: + case ConversionSpecifier::UArg: + case ConversionSpecifier::ZArg: + return false; + } + llvm_unreachable("Invalid ConversionSpecifier Kind!"); +} + +bool FormatSpecifier::hasStandardLengthConversionCombination() const { + if (LM.getKind() == LengthModifier::AsLongDouble) { + switch(CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + return false; + default: + return true; + } + } + return true; +} + +Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const { + if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) { + if (LM.getKind() == LengthModifier::AsLongDouble || + LM.getKind() == LengthModifier::AsQuad) { + LengthModifier FixedLM(LM); + FixedLM.setKind(LengthModifier::AsLongLong); + return FixedLM; + } + } + + return None; +} + +bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, + LengthModifier &LM) { + assert(isa<TypedefType>(QT) && "Expected a TypedefType"); + const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl(); + + for (;;) { + const IdentifierInfo *Identifier = Typedef->getIdentifier(); + if (Identifier->getName() == "size_t") { + LM.setKind(LengthModifier::AsSizeT); + return true; + } else if (Identifier->getName() == "ssize_t") { + // Not C99, but common in Unix. + LM.setKind(LengthModifier::AsSizeT); + return true; + } else if (Identifier->getName() == "intmax_t") { + LM.setKind(LengthModifier::AsIntMax); + return true; + } else if (Identifier->getName() == "uintmax_t") { + LM.setKind(LengthModifier::AsIntMax); + return true; + } else if (Identifier->getName() == "ptrdiff_t") { + LM.setKind(LengthModifier::AsPtrDiff); + return true; + } + + QualType T = Typedef->getUnderlyingType(); + if (!isa<TypedefType>(T)) + break; + + Typedef = cast<TypedefType>(T)->getDecl(); + } + return false; +} diff --git a/lib/AST/FormatStringParsing.h b/lib/AST/FormatStringParsing.h new file mode 100644 index 0000000000..9da829adcb --- /dev/null +++ b/lib/AST/FormatStringParsing.h @@ -0,0 +1,83 @@ +#ifndef LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H +#define LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Type.h" +#include "clang/AST/FormatString.h" + +namespace clang { + +class LangOptions; + +template <typename T> +class UpdateOnReturn { + T &ValueToUpdate; + const T &ValueToCopy; +public: + UpdateOnReturn(T &valueToUpdate, const T &valueToCopy) + : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {} + + ~UpdateOnReturn() { + ValueToUpdate = ValueToCopy; + } +}; + +namespace analyze_format_string { + +OptionalAmount ParseAmount(const char *&Beg, const char *E); +OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, + unsigned &argIndex); + +OptionalAmount ParsePositionAmount(FormatStringHandler &H, + const char *Start, const char *&Beg, + const char *E, PositionContext p); + +bool ParseFieldWidth(FormatStringHandler &H, + FormatSpecifier &CS, + const char *Start, const char *&Beg, const char *E, + unsigned *argIndex); + +bool ParseArgPosition(FormatStringHandler &H, + FormatSpecifier &CS, const char *Start, + const char *&Beg, const char *E); + +bool ParseVectorModifier(FormatStringHandler &H, + FormatSpecifier &FS, const char *&Beg, const char *E, + const LangOptions &LO); + +/// Returns true if a LengthModifier was parsed and installed in the +/// FormatSpecifier& argument, and false otherwise. +bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E, + const LangOptions &LO, bool IsScanf = false); + +/// Returns true if the invalid specifier in \p SpecifierBegin is a UTF-8 +/// string; check that it won't go further than \p FmtStrEnd and write +/// up the total size in \p Len. +bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin, + const char *FmtStrEnd, unsigned &Len); + +template <typename T> class SpecifierResult { + T FS; + const char *Start; + bool Stop; +public: + SpecifierResult(bool stop = false) + : Start(nullptr), Stop(stop) {} + SpecifierResult(const char *start, + const T &fs) + : FS(fs), Start(start), Stop(false) {} + + const char *getStart() const { return Start; } + bool shouldStop() const { return Stop; } + bool hasValue() const { return Start != nullptr; } + const T &getValue() const { + assert(hasValue()); + return FS; + } + const T &getValue() { return FS; } +}; + +} // end analyze_format_string namespace +} // end clang namespace + +#endif diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index e99549850a..d8d56216b1 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -33,12 +33,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#define MANGLE_CHECKER 0 - -#if MANGLE_CHECKER -#include <cxxabi.h> -#endif - using namespace clang; namespace { @@ -415,17 +409,6 @@ public: SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth), AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {} -#if MANGLE_CHECKER - ~CXXNameMangler() { - if (Out.str()[0] == '\01') - return; - - int status = 0; - char *result = abi::__cxa_demangle(Out.str().str().c_str(), 0, 0, &status); - assert(status == 0 && "Could not demangle mangled name!"); - free(result); - } -#endif raw_ostream &getStream() { return Out; } void disableDerivedAbiTags() { DisableDerivedAbiTags = true; } @@ -1520,8 +1503,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) { - Qualifiers MethodQuals = - Qualifiers::fromCVRUMask(Method->getTypeQualifiers()); + Qualifiers MethodQuals = Method->getTypeQualifiers(); // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); @@ -2652,6 +2634,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::OCLReserveID: Out << "13ocl_reserveid"; break; +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: \ + type_name = "ocl_" #ExtType; \ + Out << type_name.size() << type_name; \ + break; +#include "clang/Basic/OpenCLExtensionTypes.def" } } @@ -2670,6 +2658,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_X86RegCall: case CC_AAPCS: case CC_AAPCS_VFP: + case CC_AArch64VectorCall: case CC_IntelOclBicc: case CC_SpirFunction: case CC_OpenCLKernel: @@ -2735,7 +2724,7 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) { // Mangle CV-qualifiers, if present. These are 'this' qualifiers, // e.g. "const" in "int (A::*)() const". - mangleQualifiers(Qualifiers::fromCVRUMask(T->getTypeQuals())); + mangleQualifiers(T->getTypeQuals()); // Mangle instantiation-dependent exception-specification, if present, // per cxx-abi-dev proposal on 2016-10-11. @@ -3524,6 +3513,10 @@ recurse: case Expr::CXXInheritedCtorInitExprClass: llvm_unreachable("unexpected statement kind"); + case Expr::ConstantExprClass: + E = cast<ConstantExpr>(E)->getSubExpr(); + goto recurse; + // FIXME: invent manglings for all these. case Expr::BlockExprClass: case Expr::ChooseExprClass: @@ -3881,6 +3874,7 @@ recurse: case UETT_SizeOf: Out << 's'; break; + case UETT_PreferredAlignOf: case UETT_AlignOf: Out << 'a'; break; diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp index b0e5146e81..bb29bffc1b 100644 --- a/lib/AST/Mangle.cpp +++ b/lib/AST/Mangle.cpp @@ -25,12 +25,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#define MANGLE_CHECKER 0 - -#if MANGLE_CHECKER -#include <cxxabi.h> -#endif - using namespace clang; // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 1d4bdaa760..821112e7a9 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -309,7 +309,7 @@ public: const MethodVFTableLocation &ML); void mangleNumber(int64_t Number); void mangleTagTypeKind(TagTypeKind TK); - void mangleArtificalTagType(TagTypeKind TK, StringRef UnqualifiedName, + void mangleArtificialTagType(TagTypeKind TK, StringRef UnqualifiedName, ArrayRef<StringRef> NestedNames = None); void mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM = QMM_Mangle); @@ -482,7 +482,7 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD)); else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) mangleVariableEncoding(VD); - else if (!isa<ObjCInterfaceDecl>(D)) + else llvm_unreachable("Tried to mangle unexpected NamedDecl!"); } @@ -1070,7 +1070,7 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { if (PointersAre64Bit) Out << 'E'; Out << 'A'; - mangleArtificalTagType(TTK_Struct, + mangleArtificialTagType(TTK_Struct, Discriminate("__block_literal", Discriminator, ParameterDiscriminator)); Out << "@Z"; @@ -1365,7 +1365,7 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // It's a global variable. Out << '3'; // It's a struct called __s_GUID. - mangleArtificalTagType(TTK_Struct, "__s_GUID"); + mangleArtificialTagType(TTK_Struct, "__s_GUID"); // It's const. Out << 'B'; return; @@ -1521,9 +1521,9 @@ void MicrosoftCXXNameMangler::mangleObjCProtocol(const ObjCProtocolDecl *PD) { Stream << "?$"; Extra.mangleSourceName("Protocol"); - Extra.mangleArtificalTagType(TTK_Struct, PD->getName()); + Extra.mangleArtificialTagType(TTK_Struct, PD->getName()); - mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); + mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); } void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type, @@ -1552,7 +1552,7 @@ void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type, Extra.manglePointerExtQualifiers(Quals, Type); Extra.mangleType(Type, Range); - mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); + mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); } void MicrosoftCXXNameMangler::mangleObjCKindOfType(const ObjCObjectType *T, @@ -1569,7 +1569,7 @@ void MicrosoftCXXNameMangler::mangleObjCKindOfType(const ObjCObjectType *T, ->getAs<ObjCObjectType>(), Quals, Range); - mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); + mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); } void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, @@ -1765,7 +1765,7 @@ void MicrosoftCXXNameMangler::manglePassObjectSizeArg( ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); if (Found == TypeBackReferences.end()) { - mangleArtificalTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type), + mangleArtificialTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type), {"__clang"}); if (TypeBackReferences.size() < 10) { @@ -1951,13 +1951,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, llvm_unreachable("placeholder types shouldn't get to name mangling"); case BuiltinType::ObjCId: - mangleArtificalTagType(TTK_Struct, ".objc_object"); + mangleArtificialTagType(TTK_Struct, "objc_object"); break; case BuiltinType::ObjCClass: - mangleArtificalTagType(TTK_Struct, ".objc_class"); + mangleArtificialTagType(TTK_Struct, "objc_class"); break; case BuiltinType::ObjCSel: - mangleArtificalTagType(TTK_Struct, ".objc_selector"); + mangleArtificialTagType(TTK_Struct, "objc_selector"); break; #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ @@ -1967,35 +1967,40 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, #include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: Out << "PA"; - mangleArtificalTagType(TTK_Struct, "ocl_sampler"); + mangleArtificialTagType(TTK_Struct, "ocl_sampler"); break; case BuiltinType::OCLEvent: Out << "PA"; - mangleArtificalTagType(TTK_Struct, "ocl_event"); + mangleArtificialTagType(TTK_Struct, "ocl_event"); break; case BuiltinType::OCLClkEvent: Out << "PA"; - mangleArtificalTagType(TTK_Struct, "ocl_clkevent"); + mangleArtificialTagType(TTK_Struct, "ocl_clkevent"); break; case BuiltinType::OCLQueue: Out << "PA"; - mangleArtificalTagType(TTK_Struct, "ocl_queue"); + mangleArtificialTagType(TTK_Struct, "ocl_queue"); break; case BuiltinType::OCLReserveID: Out << "PA"; - mangleArtificalTagType(TTK_Struct, "ocl_reserveid"); + mangleArtificialTagType(TTK_Struct, "ocl_reserveid"); + break; +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: \ + mangleArtificialTagType(TTK_Struct, "ocl_" #ExtType); \ break; +#include "clang/Basic/OpenCLExtensionTypes.def" case BuiltinType::NullPtr: Out << "$$T"; break; case BuiltinType::Float16: - mangleArtificalTagType(TTK_Struct, "_Float16", {"__clang"}); + mangleArtificialTagType(TTK_Struct, "_Float16", {"__clang"}); break; case BuiltinType::Half: - mangleArtificalTagType(TTK_Struct, "_Half", {"__clang"}); + mangleArtificialTagType(TTK_Struct, "_Half", {"__clang"}); break; case BuiltinType::ShortAccum: @@ -2088,7 +2093,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (HasThisQuals) { - Qualifiers Quals = Qualifiers::fromCVRUMask(Proto->getTypeQuals()); + Qualifiers Quals = Proto->getTypeQuals(); manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType()); mangleRefQualifier(Proto->getRefQualifier()); mangleQualifiers(Quals, /*IsMember=*/false); @@ -2352,7 +2357,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { } // If you add a call to this, consider updating isArtificialTagType() too. -void MicrosoftCXXNameMangler::mangleArtificalTagType( +void MicrosoftCXXNameMangler::mangleArtificialTagType( TagTypeKind TK, StringRef UnqualifiedName, ArrayRef<StringRef> NestedNames) { // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @ @@ -2538,10 +2543,10 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers, Extra.mangleSourceName("_Complex"); Extra.mangleType(ElementType, Range, QMM_Escape); - mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"}); + mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"}); } -// Returns true for types that mangleArtificalTagType() gets called for with +// Returns true for types that mangleArtificialTagType() gets called for with // TTK_Union, TTK_Struct, TTK_Class and where compatibility with MSVC's // mangling matters. // (It doesn't matter for Objective-C types and the like that cl.exe doesn't @@ -2554,7 +2559,7 @@ bool MicrosoftCXXNameMangler::isArtificialTagType(QualType T) const { case Type::Vector: { // For ABI compatibility only __m64, __m128(id), and __m256(id) matter, - // but since mangleType(VectorType*) always calls mangleArtificalTagType() + // but since mangleType(VectorType*) always calls mangleArtificialTagType() // just always return true (the other vector types are clang-only). return true; } @@ -2569,18 +2574,20 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals, // Pattern match exactly the typedefs in our intrinsic headers. Anything that // doesn't match the Intel types uses a custom mangling below. size_t OutSizeBefore = Out.tell(); - 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) { - mangleArtificalTagType(TTK_Union, "__m64"); - } else if (Width >= 128) { - if (ET->getKind() == BuiltinType::Float) - mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width)); - else if (ET->getKind() == BuiltinType::LongLong) - mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i'); - else if (ET->getKind() == BuiltinType::Double) - mangleArtificalTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd'); + if (!isa<ExtVectorType>(T)) { + 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) { + mangleArtificialTagType(TTK_Union, "__m64"); + } else if (Width >= 128) { + if (ET->getKind() == BuiltinType::Float) + mangleArtificialTagType(TTK_Union, "__m" + llvm::utostr(Width)); + else if (ET->getKind() == BuiltinType::LongLong) + mangleArtificialTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i'); + else if (ET->getKind() == BuiltinType::Double) + mangleArtificialTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd'); + } } } @@ -2599,7 +2606,7 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals, Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements()), /*IsBoolean=*/false); - mangleArtificalTagType(TTK_Union, TemplateMangling, {"__clang"}); + mangleArtificialTagType(TTK_Union, TemplateMangling, {"__clang"}); } } @@ -2637,10 +2644,9 @@ void MicrosoftCXXNameMangler::mangleType(const DependentAddressSpaceType *T, void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, SourceRange) { - // ObjC interfaces are mangled as if they were structs with a name that is - // not a valid C/C++ identifier + // ObjC interfaces have structs underlying them. mangleTagTypeKind(TTK_Struct); - mangle(T->getDecl(), ".objc_cls_"); + mangleName(T->getDecl()); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, @@ -2661,11 +2667,11 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Out << "?$"; if (T->isObjCId()) - mangleSourceName(".objc_object"); + mangleSourceName("objc_object"); else if (T->isObjCClass()) - mangleSourceName(".objc_class"); + mangleSourceName("objc_class"); else - mangleSourceName((".objc_cls_" + T->getInterface()->getName()).str()); + mangleSourceName(T->getInterface()->getName()); for (const auto &Q : T->quals()) mangleObjCProtocol(Q); @@ -2804,7 +2810,7 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers, Extra.mangleSourceName("_Atomic"); Extra.mangleType(ValueType, Range, QMM_Escape); - mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"}); + mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"}); } void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers, diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp index 9d591313f2..5b8300893e 100644 --- a/lib/AST/NSAPI.cpp +++ b/lib/AST/NSAPI.cpp @@ -475,6 +475,9 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: @@ -509,7 +512,7 @@ bool NSAPI::isObjCNSUIntegerType(QualType T) const { } StringRef NSAPI::GetNSIntegralKind(QualType T) const { - if (!Ctx.getLangOpts().ObjC1 || T.isNull()) + if (!Ctx.getLangOpts().ObjC || T.isNull()) return StringRef(); while (const TypedefType *TDT = T->getAs<TypedefType>()) { @@ -561,7 +564,7 @@ bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl, bool NSAPI::isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const { - if (!Ctx.getLangOpts().ObjC1) + if (!Ctx.getLangOpts().ObjC) return false; if (T.isNull()) return false; @@ -580,7 +583,7 @@ bool NSAPI::isObjCTypedef(QualType T, bool NSAPI::isObjCEnumerator(const Expr *E, StringRef name, IdentifierInfo *&II) const { - if (!Ctx.getLangOpts().ObjC1) + if (!Ctx.getLangOpts().ObjC) return false; if (!E) return false; diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index df23972af2..548f2f8e3b 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -270,9 +271,8 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const { /// Print this nested name specifier to the given output /// stream. -void -NestedNameSpecifier::print(raw_ostream &OS, - const PrintingPolicy &Policy) const { +void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, + bool ResolveTemplateArguments) const { if (getPrefix()) getPrefix()->print(OS, Policy); @@ -305,6 +305,15 @@ NestedNameSpecifier::print(raw_ostream &OS, LLVM_FALLTHROUGH; case TypeSpec: { + const auto *Record = + dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl()); + if (ResolveTemplateArguments && Record) { + // Print the type trait with resolved template parameters. + Record->printName(OS); + printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(), + Policy); + break; + } const Type *T = getAsType(); PrintingPolicy InnerPolicy(Policy); @@ -339,13 +348,20 @@ NestedNameSpecifier::print(raw_ostream &OS, OS << "::"; } -void NestedNameSpecifier::dump(const LangOptions &LO) const { - print(llvm::errs(), PrintingPolicy(LO)); +LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const { + dump(llvm::errs(), LO); } -LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { +LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); } + +LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const { LangOptions LO; - print(llvm::errs(), PrintingPolicy(LO)); + dump(OS, LO); +} + +LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS, + const LangOptions &LO) const { + print(OS, PrintingPolicy(LO)); } unsigned diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 3aeb7e6fbb..a4c344ce0a 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -49,7 +49,7 @@ void ODRHash::AddDeclarationNameImpl(DeclarationName Name) { auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size())); ID.AddInteger(Result.first->second); if (!Result.second) { - // If found in map, the the DeclarationName has previously been processed. + // If found in map, the DeclarationName has previously been processed. return; } diff --git a/lib/AST/OSLog.cpp b/lib/AST/OSLog.cpp new file mode 100644 index 0000000000..df2f808728 --- /dev/null +++ b/lib/AST/OSLog.cpp @@ -0,0 +1,212 @@ +// TODO: header template + +#include "clang/AST/OSLog.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/FormatString.h" +#include "clang/Basic/Builtins.h" +#include "llvm/ADT/SmallBitVector.h" + +using namespace clang; + +using clang::analyze_os_log::OSLogBufferItem; +using clang::analyze_os_log::OSLogBufferLayout; + +namespace { +class OSLogFormatStringHandler + : public analyze_format_string::FormatStringHandler { +private: + struct ArgData { + const Expr *E = nullptr; + Optional<OSLogBufferItem::Kind> Kind; + Optional<unsigned> Size; + Optional<const Expr *> Count; + Optional<const Expr *> Precision; + Optional<const Expr *> FieldWidth; + unsigned char Flags = 0; + StringRef MaskType; + }; + SmallVector<ArgData, 4> ArgsData; + ArrayRef<const Expr *> Args; + + OSLogBufferItem::Kind + getKind(analyze_format_string::ConversionSpecifier::Kind K) { + switch (K) { + case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s" + return OSLogBufferItem::StringKind; + case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S" + return OSLogBufferItem::WideStringKind; + case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P" + return OSLogBufferItem::PointerKind; + case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@" + return OSLogBufferItem::ObjCObjKind; + case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m" + return OSLogBufferItem::ErrnoKind; + default: + return OSLogBufferItem::ScalarKind; + } + } + } + +public: + OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) { + ArgsData.reserve(Args.size()); + } + + virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, + const char *StartSpecifier, + unsigned SpecifierLen) { + if (!FS.consumesDataArgument() && + FS.getConversionSpecifier().getKind() != + clang::analyze_format_string::ConversionSpecifier::PrintErrno) + return true; + + ArgsData.emplace_back(); + unsigned ArgIndex = FS.getArgIndex(); + if (ArgIndex < Args.size()) + ArgsData.back().E = Args[ArgIndex]; + + // First get the Kind + ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind()); + if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind && + !ArgsData.back().E) { + // missing argument + ArgsData.pop_back(); + return false; + } + + switch (FS.getConversionSpecifier().getKind()) { + case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s" + case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S" + auto &precision = FS.getPrecision(); + switch (precision.getHowSpecified()) { + case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s" + break; + case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s" + ArgsData.back().Size = precision.getConstantAmount(); + break; + case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s" + ArgsData.back().Count = Args[precision.getArgIndex()]; + break; + case clang::analyze_format_string::OptionalAmount::Invalid: + return false; + } + break; + } + case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P" + auto &precision = FS.getPrecision(); + switch (precision.getHowSpecified()) { + case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P" + return false; // length must be supplied with pointer format specifier + case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P" + ArgsData.back().Size = precision.getConstantAmount(); + break; + case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P" + ArgsData.back().Count = Args[precision.getArgIndex()]; + break; + case clang::analyze_format_string::OptionalAmount::Invalid: + return false; + } + break; + } + default: + if (FS.getPrecision().hasDataArgument()) { + ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()]; + } + break; + } + if (FS.getFieldWidth().hasDataArgument()) { + ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()]; + } + + if (FS.isSensitive()) + ArgsData.back().Flags |= OSLogBufferItem::IsSensitive; + else if (FS.isPrivate()) + ArgsData.back().Flags |= OSLogBufferItem::IsPrivate; + else if (FS.isPublic()) + ArgsData.back().Flags |= OSLogBufferItem::IsPublic; + + ArgsData.back().MaskType = FS.getMaskType(); + return true; + } + + void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const { + Layout.Items.clear(); + for (auto &Data : ArgsData) { + if (!Data.MaskType.empty()) { + CharUnits Size = CharUnits::fromQuantity(8); + Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr, + Size, 0, Data.MaskType); + } + + if (Data.FieldWidth) { + CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType()); + Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth, + Size, 0); + } + if (Data.Precision) { + CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType()); + Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision, + Size, 0); + } + if (Data.Count) { + // "%.*P" has an extra "count" that we insert before the argument. + CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType()); + Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size, + 0); + } + if (Data.Size) + Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size), + Data.Flags); + if (Data.Kind) { + CharUnits Size; + if (*Data.Kind == OSLogBufferItem::ErrnoKind) + Size = CharUnits::Zero(); + else + Size = Ctx.getTypeSizeInChars(Data.E->getType()); + Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags); + } else { + auto Size = Ctx.getTypeSizeInChars(Data.E->getType()); + Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size, + Data.Flags); + } + } + } +}; +} // end anonymous namespace + +bool clang::analyze_os_log::computeOSLogBufferLayout( + ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) { + ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs()); + + const Expr *StringArg; + ArrayRef<const Expr *> VarArgs; + switch (E->getBuiltinCallee()) { + case Builtin::BI__builtin_os_log_format_buffer_size: + assert(E->getNumArgs() >= 1 && + "__builtin_os_log_format_buffer_size takes at least 1 argument"); + StringArg = E->getArg(0); + VarArgs = Args.slice(1); + break; + case Builtin::BI__builtin_os_log_format: + assert(E->getNumArgs() >= 2 && + "__builtin_os_log_format takes at least 2 arguments"); + StringArg = E->getArg(1); + VarArgs = Args.slice(2); + break; + default: + llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout"); + } + + const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts()); + assert(Lit && (Lit->isAscii() || Lit->isUTF8())); + StringRef Data = Lit->getString(); + OSLogFormatStringHandler H(VarArgs); + ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(), + Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false); + + H.computeLayout(Ctx, Layout); + return true; +} diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp index 1114ae3e92..3124b0ff6f 100644 --- a/lib/AST/OpenMPClause.cpp +++ b/lib/AST/OpenMPClause.cpp @@ -14,6 +14,7 @@ #include "clang/AST/OpenMPClause.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Casting.h" @@ -107,6 +108,10 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_use_device_ptr: case OMPC_is_device_ptr: case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: break; } @@ -177,6 +182,10 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_use_device_ptr: case OMPC_is_device_ptr: case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: break; } @@ -1043,3 +1052,442 @@ OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty( return new (Mem) OMPIsDevicePtrClause(NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents); } + +//===----------------------------------------------------------------------===// +// OpenMP clauses printing methods +//===----------------------------------------------------------------------===// + +void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) { + OS << "if("; + if (Node->getNameModifier() != OMPD_unknown) + OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": "; + Node->getCondition()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) { + OS << "final("; + Node->getCondition()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) { + OS << "num_threads("; + Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) { + OS << "safelen("; + Node->getSafelen()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) { + OS << "simdlen("; + Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) { + OS << "collapse("; + Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) { + OS << "default(" + << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind()) + << ")"; +} + +void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) { + OS << "proc_bind(" + << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind()) + << ")"; +} + +void OMPClausePrinter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) { + OS << "unified_address"; +} + +void OMPClausePrinter::VisitOMPUnifiedSharedMemoryClause( + OMPUnifiedSharedMemoryClause *) { + OS << "unified_shared_memory"; +} + +void OMPClausePrinter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) { + OS << "reverse_offload"; +} + +void OMPClausePrinter::VisitOMPDynamicAllocatorsClause( + OMPDynamicAllocatorsClause *) { + OS << "dynamic_allocators"; +} + +void OMPClausePrinter::VisitOMPAtomicDefaultMemOrderClause( + OMPAtomicDefaultMemOrderClause *Node) { + OS << "atomic_default_mem_order(" + << getOpenMPSimpleClauseTypeName(OMPC_atomic_default_mem_order, + Node->getAtomicDefaultMemOrderKind()) + << ")"; +} + +void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { + OS << "schedule("; + if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { + OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, + Node->getFirstScheduleModifier()); + if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { + OS << ", "; + OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, + Node->getSecondScheduleModifier()); + } + OS << ": "; + } + OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind()); + if (auto *E = Node->getChunkSize()) { + OS << ", "; + E->printPretty(OS, nullptr, Policy); + } + OS << ")"; +} + +void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) { + OS << "ordered"; + if (auto *Num = Node->getNumForLoops()) { + OS << "("; + Num->printPretty(OS, nullptr, Policy, 0); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) { + OS << "nowait"; +} + +void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) { + OS << "untied"; +} + +void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) { + OS << "nogroup"; +} + +void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) { + OS << "mergeable"; +} + +void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; } + +void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; } + +void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) { + OS << "update"; +} + +void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) { + OS << "capture"; +} + +void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) { + OS << "seq_cst"; +} + +void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) { + OS << "threads"; +} + +void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; } + +void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) { + OS << "device("; + Node->getDevice()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) { + OS << "num_teams("; + Node->getNumTeams()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) { + OS << "thread_limit("; + Node->getThreadLimit()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) { + OS << "priority("; + Node->getPriority()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) { + OS << "grainsize("; + Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) { + OS << "num_tasks("; + Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) { + OS << "hint("; + Node->getHint()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +template<typename T> +void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { + for (typename T::varlist_iterator I = Node->varlist_begin(), + E = Node->varlist_end(); + I != E; ++I) { + assert(*I && "Expected non-null Stmt"); + OS << (I == Node->varlist_begin() ? StartSym : ','); + if (auto *DRE = dyn_cast<DeclRefExpr>(*I)) { + if (isa<OMPCapturedExprDecl>(DRE->getDecl())) + DRE->printPretty(OS, nullptr, Policy, 0); + else + DRE->getDecl()->printQualifiedName(OS); + } else + (*I)->printPretty(OS, nullptr, Policy, 0); + } +} + +void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) { + if (!Node->varlist_empty()) { + OS << "private"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) { + if (!Node->varlist_empty()) { + OS << "firstprivate"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) { + if (!Node->varlist_empty()) { + OS << "lastprivate"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) { + if (!Node->varlist_empty()) { + OS << "shared"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) { + if (!Node->varlist_empty()) { + OS << "reduction("; + NestedNameSpecifier *QualifierLoc = + Node->getQualifierLoc().getNestedNameSpecifier(); + OverloadedOperatorKind OOK = + Node->getNameInfo().getName().getCXXOverloadedOperator(); + if (QualifierLoc == nullptr && OOK != OO_None) { + // Print reduction identifier in C format + OS << getOperatorSpelling(OOK); + } else { + // Use C++ format + if (QualifierLoc != nullptr) + QualifierLoc->print(OS, Policy); + OS << Node->getNameInfo(); + } + OS << ":"; + VisitOMPClauseList(Node, ' '); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPTaskReductionClause( + OMPTaskReductionClause *Node) { + if (!Node->varlist_empty()) { + OS << "task_reduction("; + NestedNameSpecifier *QualifierLoc = + Node->getQualifierLoc().getNestedNameSpecifier(); + OverloadedOperatorKind OOK = + Node->getNameInfo().getName().getCXXOverloadedOperator(); + if (QualifierLoc == nullptr && OOK != OO_None) { + // Print reduction identifier in C format + OS << getOperatorSpelling(OOK); + } else { + // Use C++ format + if (QualifierLoc != nullptr) + QualifierLoc->print(OS, Policy); + OS << Node->getNameInfo(); + } + OS << ":"; + VisitOMPClauseList(Node, ' '); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) { + if (!Node->varlist_empty()) { + OS << "in_reduction("; + NestedNameSpecifier *QualifierLoc = + Node->getQualifierLoc().getNestedNameSpecifier(); + OverloadedOperatorKind OOK = + Node->getNameInfo().getName().getCXXOverloadedOperator(); + if (QualifierLoc == nullptr && OOK != OO_None) { + // Print reduction identifier in C format + OS << getOperatorSpelling(OOK); + } else { + // Use C++ format + if (QualifierLoc != nullptr) + QualifierLoc->print(OS, Policy); + OS << Node->getNameInfo(); + } + OS << ":"; + VisitOMPClauseList(Node, ' '); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { + if (!Node->varlist_empty()) { + OS << "linear"; + if (Node->getModifierLoc().isValid()) { + OS << '(' + << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier()); + } + VisitOMPClauseList(Node, '('); + if (Node->getModifierLoc().isValid()) + OS << ')'; + if (Node->getStep() != nullptr) { + OS << ": "; + Node->getStep()->printPretty(OS, nullptr, Policy, 0); + } + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) { + if (!Node->varlist_empty()) { + OS << "aligned"; + VisitOMPClauseList(Node, '('); + if (Node->getAlignment() != nullptr) { + OS << ": "; + Node->getAlignment()->printPretty(OS, nullptr, Policy, 0); + } + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) { + if (!Node->varlist_empty()) { + OS << "copyin"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) { + if (!Node->varlist_empty()) { + OS << "copyprivate"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) { + if (!Node->varlist_empty()) { + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) { + OS << "depend("; + OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), + Node->getDependencyKind()); + if (!Node->varlist_empty()) { + OS << " :"; + VisitOMPClauseList(Node, ' '); + } + OS << ")"; +} + +void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) { + if (!Node->varlist_empty()) { + OS << "map("; + if (Node->getMapType() != OMPC_MAP_unknown) { + if (Node->getMapTypeModifier() != OMPC_MAP_unknown) { + OS << getOpenMPSimpleClauseTypeName(OMPC_map, + Node->getMapTypeModifier()); + OS << ','; + } + OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType()); + OS << ':'; + } + VisitOMPClauseList(Node, ' '); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) { + if (!Node->varlist_empty()) { + OS << "to"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) { + if (!Node->varlist_empty()) { + OS << "from"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) { + OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName( + OMPC_dist_schedule, Node->getDistScheduleKind()); + if (auto *E = Node->getChunkSize()) { + OS << ", "; + E->printPretty(OS, nullptr, Policy); + } + OS << ")"; +} + +void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) { + OS << "defaultmap("; + OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap, + Node->getDefaultmapModifier()); + OS << ": "; + OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap, + Node->getDefaultmapKind()); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) { + if (!Node->varlist_empty()) { + OS << "use_device_ptr"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) { + if (!Node->varlist_empty()) { + OS << "is_device_ptr"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp index af2a480dc2..88c178aa37 100644 --- a/lib/AST/ParentMap.cpp +++ b/lib/AST/ParentMap.cpp @@ -163,7 +163,7 @@ bool ParentMap::isConsumedExpr(Expr* E) const { // Ignore parents that don't guarantee consumption. while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) || - isa<ExprWithCleanups>(P))) { + isa<FullExpr>(P))) { DirectChild = P; P = getParent(P); } diff --git a/lib/AST/PrintfFormatString.cpp b/lib/AST/PrintfFormatString.cpp new file mode 100644 index 0000000000..e0a0c5b758 --- /dev/null +++ b/lib/AST/PrintfFormatString.cpp @@ -0,0 +1,1075 @@ +//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Handling of format string in printf and friends. The structure of format +// strings for fprintf() are described in C99 7.19.6.1. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/FormatString.h" +#include "clang/AST/OSLog.h" +#include "FormatStringParsing.h" +#include "clang/Basic/TargetInfo.h" + +using clang::analyze_format_string::ArgType; +using clang::analyze_format_string::FormatStringHandler; +using clang::analyze_format_string::LengthModifier; +using clang::analyze_format_string::OptionalAmount; +using clang::analyze_format_string::ConversionSpecifier; +using clang::analyze_printf::PrintfSpecifier; + +using namespace clang; + +typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier> + PrintfSpecifierResult; + +//===----------------------------------------------------------------------===// +// Methods for parsing format strings. +//===----------------------------------------------------------------------===// + +using analyze_format_string::ParseNonPositionAmount; + +static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, + const char *Start, const char *&Beg, const char *E, + unsigned *argIndex) { + if (argIndex) { + FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); + } else { + const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, + analyze_format_string::PrecisionPos); + if (Amt.isInvalid()) + return true; + FS.setPrecision(Amt); + } + return false; +} + +static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS, + const char *FlagBeg, const char *E, bool Warn) { + StringRef Flag(FlagBeg, E - FlagBeg); + // Currently there is only one flag. + if (Flag == "tt") { + FS.setHasObjCTechnicalTerm(FlagBeg); + return false; + } + // Handle either the case of no flag or an invalid flag. + if (Warn) { + if (Flag == "") + H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg); + else + H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg); + } + return true; +} + +static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, + const char *&Beg, + const char *E, + unsigned &argIndex, + const LangOptions &LO, + const TargetInfo &Target, + bool Warn, + bool isFreeBSDKPrintf) { + + using namespace clang::analyze_format_string; + using namespace clang::analyze_printf; + + const char *I = Beg; + const char *Start = nullptr; + UpdateOnReturn <const char*> UpdateBeg(Beg, I); + + // Look for a '%' character that indicates the start of a format specifier. + for ( ; I != E ; ++I) { + char c = *I; + if (c == '\0') { + // Detect spurious null characters, which are likely errors. + H.HandleNullChar(I); + return true; + } + if (c == '%') { + Start = I++; // Record the start of the format specifier. + break; + } + } + + // No format specifier found? + if (!Start) + return false; + + if (I == E) { + // No more characters left? + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + PrintfSpecifier FS; + if (ParseArgPosition(H, FS, Start, I, E)) + return true; + + if (I == E) { + // No more characters left? + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + if (*I == '{') { + ++I; + unsigned char PrivacyFlags = 0; + StringRef MatchedStr; + + do { + StringRef Str(I, E - I); + std::string Match = "^[[:space:]]*" + "(private|public|sensitive|mask\\.[^[:space:],}]*)" + "[[:space:]]*(,|})"; + llvm::Regex R(Match); + SmallVector<StringRef, 2> Matches; + + if (R.match(Str, &Matches)) { + MatchedStr = Matches[1]; + I += Matches[0].size(); + + // Set the privacy flag if the privacy annotation in the + // comma-delimited segment is at least as strict as the privacy + // annotations in previous comma-delimited segments. + if (MatchedStr.startswith("mask")) { + StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1); + unsigned Size = MaskType.size(); + if (Warn && (Size == 0 || Size > 8)) + H.handleInvalidMaskType(MaskType); + FS.setMaskType(MaskType); + } else if (MatchedStr.equals("sensitive")) + PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive; + else if (PrivacyFlags != + clang::analyze_os_log::OSLogBufferItem::IsSensitive && + MatchedStr.equals("private")) + PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate; + else if (PrivacyFlags == 0 && MatchedStr.equals("public")) + PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic; + } else { + size_t CommaOrBracePos = + Str.find_if([](char c) { return c == ',' || c == '}'; }); + + if (CommaOrBracePos == StringRef::npos) { + // Neither a comma nor the closing brace was found. + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + I += CommaOrBracePos + 1; + } + // Continue until the closing brace is found. + } while (*(I - 1) == ','); + + // Set the privacy flag. + switch (PrivacyFlags) { + case 0: + break; + case clang::analyze_os_log::OSLogBufferItem::IsPrivate: + FS.setIsPrivate(MatchedStr.data()); + break; + case clang::analyze_os_log::OSLogBufferItem::IsPublic: + FS.setIsPublic(MatchedStr.data()); + break; + case clang::analyze_os_log::OSLogBufferItem::IsSensitive: + FS.setIsSensitive(MatchedStr.data()); + break; + default: + llvm_unreachable("Unexpected privacy flag value"); + } + } + + // Look for flags (if any). + bool hasMore = true; + for ( ; I != E; ++I) { + switch (*I) { + default: hasMore = false; break; + case '\'': + // FIXME: POSIX specific. Always accept? + FS.setHasThousandsGrouping(I); + break; + case '-': FS.setIsLeftJustified(I); break; + case '+': FS.setHasPlusPrefix(I); break; + case ' ': FS.setHasSpacePrefix(I); break; + case '#': FS.setHasAlternativeForm(I); break; + case '0': FS.setHasLeadingZeros(I); break; + } + if (!hasMore) + break; + } + + if (I == E) { + // No more characters left? + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + // Look for the field width (if any). + if (ParseFieldWidth(H, FS, Start, I, E, + FS.usesPositionalArg() ? nullptr : &argIndex)) + return true; + + if (I == E) { + // No more characters left? + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + // Look for the precision (if any). + if (*I == '.') { + ++I; + if (I == E) { + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + if (ParsePrecision(H, FS, Start, I, E, + FS.usesPositionalArg() ? nullptr : &argIndex)) + return true; + + if (I == E) { + // No more characters left? + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + } + + if (ParseVectorModifier(H, FS, I, E, LO)) + return true; + + // Look for the length modifier. + if (ParseLengthModifier(FS, I, E, LO) && I == E) { + // No more characters left? + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + // Look for the Objective-C modifier flags, if any. + // We parse these here, even if they don't apply to + // the conversion specifier, and then emit an error + // later if the conversion specifier isn't '@'. This + // enables better recovery, and we don't know if + // these flags are applicable until later. + const char *ObjCModifierFlagsStart = nullptr, + *ObjCModifierFlagsEnd = nullptr; + if (*I == '[') { + ObjCModifierFlagsStart = I; + ++I; + auto flagStart = I; + for (;; ++I) { + ObjCModifierFlagsEnd = I; + if (I == E) { + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + // Did we find the closing ']'? + if (*I == ']') { + if (ParseObjCFlags(H, FS, flagStart, I, Warn)) + return true; + ++I; + break; + } + // There are no separators defined yet for multiple + // Objective-C modifier flags. When those are + // defined, this is the place to check. + } + } + + if (*I == '\0') { + // Detect spurious null characters, which are likely errors. + H.HandleNullChar(I); + return true; + } + + // Finally, look for the conversion specifier. + const char *conversionPosition = I++; + ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; + switch (*conversionPosition) { + default: + break; + // C99: 7.19.6.1 (section 8). + case '%': k = ConversionSpecifier::PercentArg; break; + case 'A': k = ConversionSpecifier::AArg; break; + case 'E': k = ConversionSpecifier::EArg; break; + case 'F': k = ConversionSpecifier::FArg; break; + case 'G': k = ConversionSpecifier::GArg; break; + case 'X': k = ConversionSpecifier::XArg; break; + case 'a': k = ConversionSpecifier::aArg; break; + case 'c': k = ConversionSpecifier::cArg; break; + case 'd': k = ConversionSpecifier::dArg; break; + case 'e': k = ConversionSpecifier::eArg; break; + case 'f': k = ConversionSpecifier::fArg; break; + case 'g': k = ConversionSpecifier::gArg; break; + case 'i': k = ConversionSpecifier::iArg; break; + case 'n': k = ConversionSpecifier::nArg; break; + case 'o': k = ConversionSpecifier::oArg; break; + case 'p': k = ConversionSpecifier::pArg; break; + case 's': k = ConversionSpecifier::sArg; break; + case 'u': k = ConversionSpecifier::uArg; break; + case 'x': k = ConversionSpecifier::xArg; break; + // POSIX specific. + case 'C': k = ConversionSpecifier::CArg; break; + case 'S': k = ConversionSpecifier::SArg; break; + // Apple extension for os_log + case 'P': + k = ConversionSpecifier::PArg; + break; + // Objective-C. + case '@': k = ConversionSpecifier::ObjCObjArg; break; + // Glibc specific. + case 'm': k = ConversionSpecifier::PrintErrno; break; + // FreeBSD kernel specific. + case 'b': + if (isFreeBSDKPrintf) + k = ConversionSpecifier::FreeBSDbArg; // int followed by char * + break; + case 'r': + if (isFreeBSDKPrintf) + k = ConversionSpecifier::FreeBSDrArg; // int + break; + case 'y': + if (isFreeBSDKPrintf) + k = ConversionSpecifier::FreeBSDyArg; // int + break; + // Apple-specific. + case 'D': + if (isFreeBSDKPrintf) + k = ConversionSpecifier::FreeBSDDArg; // void * followed by char * + else if (Target.getTriple().isOSDarwin()) + k = ConversionSpecifier::DArg; + break; + case 'O': + if (Target.getTriple().isOSDarwin()) + k = ConversionSpecifier::OArg; + break; + case 'U': + if (Target.getTriple().isOSDarwin()) + k = ConversionSpecifier::UArg; + break; + // MS specific. + case 'Z': + if (Target.getTriple().isOSMSVCRT()) + k = ConversionSpecifier::ZArg; + break; + } + + // Check to see if we used the Objective-C modifier flags with + // a conversion specifier other than '@'. + if (k != ConversionSpecifier::ObjCObjArg && + k != ConversionSpecifier::InvalidSpecifier && + ObjCModifierFlagsStart) { + H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart, + ObjCModifierFlagsEnd + 1, + conversionPosition); + return true; + } + + PrintfConversionSpecifier CS(conversionPosition, k); + FS.setConversionSpecifier(CS); + if (CS.consumesDataArgument() && !FS.usesPositionalArg()) + FS.setArgIndex(argIndex++); + // FreeBSD kernel specific. + if (k == ConversionSpecifier::FreeBSDbArg || + k == ConversionSpecifier::FreeBSDDArg) + argIndex++; + + if (k == ConversionSpecifier::InvalidSpecifier) { + unsigned Len = I - Start; + if (ParseUTF8InvalidSpecifier(Start, E, Len)) { + CS.setEndScanList(Start + Len); + FS.setConversionSpecifier(CS); + } + // Assume the conversion takes one argument. + return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len); + } + return PrintfSpecifierResult(Start, FS); +} + +bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, + const char *I, + const char *E, + const LangOptions &LO, + const TargetInfo &Target, + bool isFreeBSDKPrintf) { + + unsigned argIndex = 0; + + // Keep looking for a format specifier until we have exhausted the string. + while (I != E) { + const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, + LO, Target, true, + isFreeBSDKPrintf); + // Did a fail-stop error of any kind occur when parsing the specifier? + // If so, don't do any more processing. + if (FSR.shouldStop()) + return true; + // Did we exhaust the string or encounter an error that + // we can recover from? + if (!FSR.hasValue()) + continue; + // We have a format specifier. Pass it to the callback. + if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(), + I - FSR.getStart())) + return true; + } + assert(I == E && "Format string not exhausted"); + return false; +} + +bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I, + const char *E, + const LangOptions &LO, + const TargetInfo &Target) { + + unsigned argIndex = 0; + + // Keep looking for a %s format specifier until we have exhausted the string. + FormatStringHandler H; + while (I != E) { + const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, + LO, Target, false, + false); + // Did a fail-stop error of any kind occur when parsing the specifier? + // If so, don't do any more processing. + if (FSR.shouldStop()) + return false; + // Did we exhaust the string or encounter an error that + // we can recover from? + if (!FSR.hasValue()) + continue; + const analyze_printf::PrintfSpecifier &FS = FSR.getValue(); + // Return true if this a %s format specifier. + if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg) + return true; + } + return false; +} + +//===----------------------------------------------------------------------===// +// Methods on PrintfSpecifier. +//===----------------------------------------------------------------------===// + +ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, + bool IsObjCLiteral) const { + if (CS.getKind() == ConversionSpecifier::cArg) + switch (LM.getKind()) { + case LengthModifier::None: + return Ctx.IntTy; + case LengthModifier::AsLong: + case LengthModifier::AsWide: + return ArgType(ArgType::WIntTy, "wint_t"); + case LengthModifier::AsShort: + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) + return Ctx.IntTy; + LLVM_FALLTHROUGH; + default: + return ArgType::Invalid(); + } + + if (CS.isIntArg()) + switch (LM.getKind()) { + case LengthModifier::AsLongDouble: + // GNU extension. + return Ctx.LongLongTy; + case LengthModifier::None: + return Ctx.IntTy; + case LengthModifier::AsInt32: + return ArgType(Ctx.IntTy, "__int32"); + case LengthModifier::AsChar: return ArgType::AnyCharTy; + case LengthModifier::AsShort: return Ctx.ShortTy; + case LengthModifier::AsLong: return Ctx.LongTy; + case LengthModifier::AsLongLong: + case LengthModifier::AsQuad: + return Ctx.LongLongTy; + case LengthModifier::AsInt64: + return ArgType(Ctx.LongLongTy, "__int64"); + case LengthModifier::AsIntMax: + return ArgType(Ctx.getIntMaxType(), "intmax_t"); + case LengthModifier::AsSizeT: + return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t")); + case LengthModifier::AsInt3264: + return Ctx.getTargetInfo().getTriple().isArch64Bit() + ? ArgType(Ctx.LongLongTy, "__int64") + : ArgType(Ctx.IntTy, "__int32"); + case LengthModifier::AsPtrDiff: + return ArgType::makePtrdiffT( + ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + case LengthModifier::AsWide: + return ArgType::Invalid(); + } + + if (CS.isUIntArg()) + switch (LM.getKind()) { + case LengthModifier::AsLongDouble: + // GNU extension. + return Ctx.UnsignedLongLongTy; + case LengthModifier::None: + return Ctx.UnsignedIntTy; + case LengthModifier::AsInt32: + return ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); + case LengthModifier::AsChar: return Ctx.UnsignedCharTy; + case LengthModifier::AsShort: return Ctx.UnsignedShortTy; + case LengthModifier::AsLong: return Ctx.UnsignedLongTy; + case LengthModifier::AsLongLong: + case LengthModifier::AsQuad: + return Ctx.UnsignedLongLongTy; + case LengthModifier::AsInt64: + return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"); + case LengthModifier::AsIntMax: + return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); + case LengthModifier::AsSizeT: + return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t")); + case LengthModifier::AsInt3264: + return Ctx.getTargetInfo().getTriple().isArch64Bit() + ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") + : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); + case LengthModifier::AsPtrDiff: + return ArgType::makePtrdiffT( + ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + case LengthModifier::AsWide: + return ArgType::Invalid(); + } + + if (CS.isDoubleArg()) { + if (LM.getKind() == LengthModifier::AsLongDouble) + return Ctx.LongDoubleTy; + return Ctx.DoubleTy; + } + + if (CS.getKind() == ConversionSpecifier::nArg) { + switch (LM.getKind()) { + case LengthModifier::None: + return ArgType::PtrTo(Ctx.IntTy); + case LengthModifier::AsChar: + return ArgType::PtrTo(Ctx.SignedCharTy); + case LengthModifier::AsShort: + return ArgType::PtrTo(Ctx.ShortTy); + case LengthModifier::AsLong: + return ArgType::PtrTo(Ctx.LongTy); + case LengthModifier::AsLongLong: + case LengthModifier::AsQuad: + return ArgType::PtrTo(Ctx.LongLongTy); + case LengthModifier::AsIntMax: + return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); + case LengthModifier::AsSizeT: + return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t")); + case LengthModifier::AsPtrDiff: + return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); + case LengthModifier::AsLongDouble: + return ArgType(); // FIXME: Is this a known extension? + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + case LengthModifier::AsInt32: + case LengthModifier::AsInt3264: + case LengthModifier::AsInt64: + case LengthModifier::AsWide: + return ArgType::Invalid(); + } + } + + switch (CS.getKind()) { + case ConversionSpecifier::sArg: + if (LM.getKind() == LengthModifier::AsWideChar) { + if (IsObjCLiteral) + return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), + "const unichar *"); + return ArgType(ArgType::WCStrTy, "wchar_t *"); + } + if (LM.getKind() == LengthModifier::AsWide) + return ArgType(ArgType::WCStrTy, "wchar_t *"); + return ArgType::CStrTy; + case ConversionSpecifier::SArg: + if (IsObjCLiteral) + return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), + "const unichar *"); + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && + LM.getKind() == LengthModifier::AsShort) + return ArgType::CStrTy; + return ArgType(ArgType::WCStrTy, "wchar_t *"); + case ConversionSpecifier::CArg: + if (IsObjCLiteral) + return ArgType(Ctx.UnsignedShortTy, "unichar"); + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && + LM.getKind() == LengthModifier::AsShort) + return Ctx.IntTy; + return ArgType(Ctx.WideCharTy, "wchar_t"); + case ConversionSpecifier::pArg: + case ConversionSpecifier::PArg: + return ArgType::CPointerTy; + case ConversionSpecifier::ObjCObjArg: + return ArgType::ObjCPointerTy; + default: + break; + } + + // FIXME: Handle other cases. + return ArgType(); +} + + +ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, + bool IsObjCLiteral) const { + const PrintfConversionSpecifier &CS = getConversionSpecifier(); + + if (!CS.consumesDataArgument()) + return ArgType::Invalid(); + + ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral); + if (!ScalarTy.isValid() || VectorNumElts.isInvalid()) + return ScalarTy; + + return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount()); +} + +bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, + ASTContext &Ctx, bool IsObjCLiteral) { + // %n is different from other conversion specifiers; don't try to fix it. + if (CS.getKind() == ConversionSpecifier::nArg) + return false; + + // Handle Objective-C objects first. Note that while the '%@' specifier will + // not warn for structure pointer or void pointer arguments (because that's + // how CoreFoundation objects are implemented), we only show a fixit for '%@' + // if we know it's an object (block, id, class, or __attribute__((NSObject))). + if (QT->isObjCRetainableType()) { + if (!IsObjCLiteral) + return false; + + CS.setKind(ConversionSpecifier::ObjCObjArg); + + // Disable irrelevant flags + HasThousandsGrouping = false; + HasPlusPrefix = false; + HasSpacePrefix = false; + HasAlternativeForm = false; + HasLeadingZeroes = false; + Precision.setHowSpecified(OptionalAmount::NotSpecified); + LM.setKind(LengthModifier::None); + + return true; + } + + // Handle strings next (char *, wchar_t *) + if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { + CS.setKind(ConversionSpecifier::sArg); + + // Disable irrelevant flags + HasAlternativeForm = 0; + HasLeadingZeroes = 0; + + // Set the long length modifier for wide characters + if (QT->getPointeeType()->isWideCharType()) + LM.setKind(LengthModifier::AsWideChar); + else + LM.setKind(LengthModifier::None); + + return true; + } + + // If it's an enum, get its underlying type. + if (const EnumType *ETy = QT->getAs<EnumType>()) + QT = ETy->getDecl()->getIntegerType(); + + const BuiltinType *BT = QT->getAs<BuiltinType>(); + if (!BT) { + const VectorType *VT = QT->getAs<VectorType>(); + if (VT) { + QT = VT->getElementType(); + BT = QT->getAs<BuiltinType>(); + VectorNumElts = OptionalAmount(VT->getNumElements()); + } + } + + // We can only work with builtin types. + if (!BT) + return false; + + // Set length modifier + switch (BT->getKind()) { + case BuiltinType::Bool: + case BuiltinType::WChar_U: + case BuiltinType::WChar_S: + case BuiltinType::Char8: // FIXME: Treat like 'char'? + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::UInt128: + case BuiltinType::Int128: + case BuiltinType::Half: + case BuiltinType::Float16: + case BuiltinType::Float128: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: + // Various types which are non-trivial to correct. + return false; + +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" +#define SIGNED_TYPE(Id, SingletonId) +#define UNSIGNED_TYPE(Id, SingletonId) +#define FLOATING_TYPE(Id, SingletonId) +#define BUILTIN_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" + // Misc other stuff which doesn't make sense here. + return false; + + case BuiltinType::UInt: + case BuiltinType::Int: + case BuiltinType::Float: + case BuiltinType::Double: + LM.setKind(LengthModifier::None); + break; + + case BuiltinType::Char_U: + case BuiltinType::UChar: + case BuiltinType::Char_S: + case BuiltinType::SChar: + LM.setKind(LengthModifier::AsChar); + break; + + case BuiltinType::Short: + case BuiltinType::UShort: + LM.setKind(LengthModifier::AsShort); + break; + + case BuiltinType::Long: + case BuiltinType::ULong: + LM.setKind(LengthModifier::AsLong); + break; + + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + LM.setKind(LengthModifier::AsLongLong); + break; + + case BuiltinType::LongDouble: + LM.setKind(LengthModifier::AsLongDouble); + break; + } + + // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. + if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) + namedTypeToLengthModifier(QT, LM); + + // If fixing the length modifier was enough, we might be done. + if (hasValidLengthModifier(Ctx.getTargetInfo())) { + // If we're going to offer a fix anyway, make sure the sign matches. + switch (CS.getKind()) { + case ConversionSpecifier::uArg: + case ConversionSpecifier::UArg: + if (QT->isSignedIntegerType()) + CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg); + break; + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + if (QT->isUnsignedIntegerType() && !HasPlusPrefix) + CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg); + break; + default: + // Other specifiers do not have signed/unsigned variants. + break; + } + + const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral); + if (ATR.isValid() && ATR.matchesType(Ctx, QT)) + return true; + } + + // Set conversion specifier and disable any flags which do not apply to it. + // Let typedefs to char fall through to int, as %c is silly for uint8_t. + if (!isa<TypedefType>(QT) && QT->isCharType()) { + CS.setKind(ConversionSpecifier::cArg); + LM.setKind(LengthModifier::None); + Precision.setHowSpecified(OptionalAmount::NotSpecified); + HasAlternativeForm = 0; + HasLeadingZeroes = 0; + HasPlusPrefix = 0; + } + // Test for Floating type first as LongDouble can pass isUnsignedIntegerType + else if (QT->isRealFloatingType()) { + CS.setKind(ConversionSpecifier::fArg); + } + else if (QT->isSignedIntegerType()) { + CS.setKind(ConversionSpecifier::dArg); + HasAlternativeForm = 0; + } + else if (QT->isUnsignedIntegerType()) { + CS.setKind(ConversionSpecifier::uArg); + HasAlternativeForm = 0; + HasPlusPrefix = 0; + } else { + llvm_unreachable("Unexpected type"); + } + + return true; +} + +void PrintfSpecifier::toString(raw_ostream &os) const { + // Whilst some features have no defined order, we are using the order + // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1) + os << "%"; + + // Positional args + if (usesPositionalArg()) { + os << getPositionalArgIndex() << "$"; + } + + // Conversion flags + if (IsLeftJustified) os << "-"; + if (HasPlusPrefix) os << "+"; + if (HasSpacePrefix) os << " "; + if (HasAlternativeForm) os << "#"; + if (HasLeadingZeroes) os << "0"; + + // Minimum field width + FieldWidth.toString(os); + // Precision + Precision.toString(os); + + // Vector modifier + if (!VectorNumElts.isInvalid()) + os << 'v' << VectorNumElts.getConstantAmount(); + + // Length modifier + os << LM.toString(); + // Conversion specifier + os << CS.toString(); +} + +bool PrintfSpecifier::hasValidPlusPrefix() const { + if (!HasPlusPrefix) + return true; + + // The plus prefix only makes sense for signed conversions + switch (CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + return true; + + default: + return false; + } +} + +bool PrintfSpecifier::hasValidAlternativeForm() const { + if (!HasAlternativeForm) + return true; + + // Alternate form flag only valid with the oxXaAeEfFgG conversions + switch (CS.getKind()) { + case ConversionSpecifier::oArg: + case ConversionSpecifier::OArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + return true; + + default: + return false; + } +} + +bool PrintfSpecifier::hasValidLeadingZeros() const { + if (!HasLeadingZeroes) + return true; + + // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions + switch (CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::OArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::UArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + return true; + + default: + return false; + } +} + +bool PrintfSpecifier::hasValidSpacePrefix() const { + if (!HasSpacePrefix) + return true; + + // The space prefix only makes sense for signed conversions + switch (CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + return true; + + default: + return false; + } +} + +bool PrintfSpecifier::hasValidLeftJustified() const { + if (!IsLeftJustified) + return true; + + // The left justified flag is valid for all conversions except n + switch (CS.getKind()) { + case ConversionSpecifier::nArg: + return false; + + default: + return true; + } +} + +bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const { + if (!HasThousandsGrouping) + return true; + + switch (CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::UArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + return true; + default: + return false; + } +} + +bool PrintfSpecifier::hasValidPrecision() const { + if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) + return true; + + // Precision is only valid with the diouxXaAeEfFgGsP conversions + switch (CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::OArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::UArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + case ConversionSpecifier::PArg: + return true; + + default: + return false; + } +} +bool PrintfSpecifier::hasValidFieldWidth() const { + if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) + return true; + + // The field width is valid for all conversions except n + switch (CS.getKind()) { + case ConversionSpecifier::nArg: + return false; + + default: + return true; + } +} diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp index 1f504fb7dd..ab873a3964 100644 --- a/lib/AST/RawCommentList.cpp +++ b/lib/AST/RawCommentList.cpp @@ -415,7 +415,7 @@ std::string RawComment::getFormattedText(const SourceManager &SourceMgr, Str.pop_back(); }; - // Proces first line separately to remember indent for the following lines. + // Process first line separately to remember indent for the following lines. if (!LexLine(/*IsFirstLine=*/true)) { DropTrailingNewLines(Result); return Result; diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 6f71d5b83e..62dc22c814 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -9,6 +9,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" @@ -16,7 +17,6 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" @@ -2829,15 +2829,14 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { 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) + if (!External.getExternalVBaseOffset(BaseDecl, BaseOffset)) + BaseOffset = Size; + } else BaseOffset = Size.alignTo(Info.Alignment); + assert(BaseOffset >= Size && "base offset already allocated"); + VBases.insert(std::make_pair(BaseDecl, ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp))); Size = BaseOffset + BaseLayout.getNonVirtualSize(); diff --git a/lib/AST/ScanfFormatString.cpp b/lib/AST/ScanfFormatString.cpp new file mode 100644 index 0000000000..bda97c57c8 --- /dev/null +++ b/lib/AST/ScanfFormatString.cpp @@ -0,0 +1,563 @@ +//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Handling of format string in scanf and friends. The structure of format +// strings for fscanf() are described in C99 7.19.6.2. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/FormatString.h" +#include "FormatStringParsing.h" +#include "clang/Basic/TargetInfo.h" + +using clang::analyze_format_string::ArgType; +using clang::analyze_format_string::FormatStringHandler; +using clang::analyze_format_string::LengthModifier; +using clang::analyze_format_string::OptionalAmount; +using clang::analyze_format_string::ConversionSpecifier; +using clang::analyze_scanf::ScanfConversionSpecifier; +using clang::analyze_scanf::ScanfSpecifier; +using clang::UpdateOnReturn; +using namespace clang; + +typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier> + ScanfSpecifierResult; + +static bool ParseScanList(FormatStringHandler &H, + ScanfConversionSpecifier &CS, + const char *&Beg, const char *E) { + const char *I = Beg; + const char *start = I - 1; + UpdateOnReturn <const char*> UpdateBeg(Beg, I); + + // No more characters? + if (I == E) { + H.HandleIncompleteScanList(start, I); + return true; + } + + // Special case: ']' is the first character. + if (*I == ']') { + if (++I == E) { + H.HandleIncompleteScanList(start, I - 1); + return true; + } + } + + // Special case: "^]" are the first characters. + if (I + 1 != E && I[0] == '^' && I[1] == ']') { + I += 2; + if (I == E) { + H.HandleIncompleteScanList(start, I - 1); + return true; + } + } + + // Look for a ']' character which denotes the end of the scan list. + while (*I != ']') { + if (++I == E) { + H.HandleIncompleteScanList(start, I - 1); + return true; + } + } + + CS.setEndScanList(I); + return false; +} + +// FIXME: Much of this is copy-paste from ParsePrintfSpecifier. +// We can possibly refactor. +static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H, + const char *&Beg, + const char *E, + unsigned &argIndex, + const LangOptions &LO, + const TargetInfo &Target) { + using namespace clang::analyze_format_string; + using namespace clang::analyze_scanf; + const char *I = Beg; + const char *Start = nullptr; + UpdateOnReturn <const char*> UpdateBeg(Beg, I); + + // Look for a '%' character that indicates the start of a format specifier. + for ( ; I != E ; ++I) { + char c = *I; + if (c == '\0') { + // Detect spurious null characters, which are likely errors. + H.HandleNullChar(I); + return true; + } + if (c == '%') { + Start = I++; // Record the start of the format specifier. + break; + } + } + + // No format specifier found? + if (!Start) + return false; + + if (I == E) { + // No more characters left? + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + ScanfSpecifier FS; + if (ParseArgPosition(H, FS, Start, I, E)) + return true; + + if (I == E) { + // No more characters left? + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + // Look for '*' flag if it is present. + if (*I == '*') { + FS.setSuppressAssignment(I); + if (++I == E) { + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + } + + // Look for the field width (if any). Unlike printf, this is either + // a fixed integer or isn't present. + const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E); + if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) { + assert(Amt.getHowSpecified() == OptionalAmount::Constant); + FS.setFieldWidth(Amt); + + if (I == E) { + // No more characters left? + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + } + + // Look for the length modifier. + if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) { + // No more characters left? + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + + // Detect spurious null characters, which are likely errors. + if (*I == '\0') { + H.HandleNullChar(I); + return true; + } + + // Finally, look for the conversion specifier. + const char *conversionPosition = I++; + ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier; + switch (*conversionPosition) { + default: + break; + case '%': k = ConversionSpecifier::PercentArg; break; + case 'A': k = ConversionSpecifier::AArg; break; + case 'E': k = ConversionSpecifier::EArg; break; + case 'F': k = ConversionSpecifier::FArg; break; + case 'G': k = ConversionSpecifier::GArg; break; + case 'X': k = ConversionSpecifier::XArg; break; + case 'a': k = ConversionSpecifier::aArg; break; + case 'd': k = ConversionSpecifier::dArg; break; + case 'e': k = ConversionSpecifier::eArg; break; + case 'f': k = ConversionSpecifier::fArg; break; + case 'g': k = ConversionSpecifier::gArg; break; + case 'i': k = ConversionSpecifier::iArg; break; + case 'n': k = ConversionSpecifier::nArg; break; + case 'c': k = ConversionSpecifier::cArg; break; + case 'C': k = ConversionSpecifier::CArg; break; + case 'S': k = ConversionSpecifier::SArg; break; + case '[': k = ConversionSpecifier::ScanListArg; break; + case 'u': k = ConversionSpecifier::uArg; break; + case 'x': k = ConversionSpecifier::xArg; break; + case 'o': k = ConversionSpecifier::oArg; break; + case 's': k = ConversionSpecifier::sArg; break; + case 'p': k = ConversionSpecifier::pArg; break; + // Apple extensions + // Apple-specific + case 'D': + if (Target.getTriple().isOSDarwin()) + k = ConversionSpecifier::DArg; + break; + case 'O': + if (Target.getTriple().isOSDarwin()) + k = ConversionSpecifier::OArg; + break; + case 'U': + if (Target.getTriple().isOSDarwin()) + k = ConversionSpecifier::UArg; + break; + } + ScanfConversionSpecifier CS(conversionPosition, k); + if (k == ScanfConversionSpecifier::ScanListArg) { + if (ParseScanList(H, CS, I, E)) + return true; + } + FS.setConversionSpecifier(CS); + if (CS.consumesDataArgument() && !FS.getSuppressAssignment() + && !FS.usesPositionalArg()) + FS.setArgIndex(argIndex++); + + // FIXME: '%' and '*' doesn't make sense. Issue a warning. + // FIXME: 'ConsumedSoFar' and '*' doesn't make sense. + + if (k == ScanfConversionSpecifier::InvalidSpecifier) { + unsigned Len = I - Beg; + if (ParseUTF8InvalidSpecifier(Beg, E, Len)) { + CS.setEndScanList(Beg + Len); + FS.setConversionSpecifier(CS); + } + // Assume the conversion takes one argument. + return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len); + } + return ScanfSpecifierResult(Start, FS); +} + +ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { + const ScanfConversionSpecifier &CS = getConversionSpecifier(); + + if (!CS.consumesDataArgument()) + return ArgType::Invalid(); + + switch(CS.getKind()) { + // Signed int. + case ConversionSpecifier::dArg: + case ConversionSpecifier::DArg: + case ConversionSpecifier::iArg: + switch (LM.getKind()) { + case LengthModifier::None: + return ArgType::PtrTo(Ctx.IntTy); + case LengthModifier::AsChar: + return ArgType::PtrTo(ArgType::AnyCharTy); + case LengthModifier::AsShort: + return ArgType::PtrTo(Ctx.ShortTy); + case LengthModifier::AsLong: + return ArgType::PtrTo(Ctx.LongTy); + case LengthModifier::AsLongLong: + case LengthModifier::AsQuad: + return ArgType::PtrTo(Ctx.LongLongTy); + case LengthModifier::AsInt64: + return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64")); + case LengthModifier::AsIntMax: + return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); + case LengthModifier::AsSizeT: + return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t")); + case LengthModifier::AsPtrDiff: + return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); + case LengthModifier::AsLongDouble: + // GNU extension. + return ArgType::PtrTo(Ctx.LongLongTy); + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + case LengthModifier::AsInt32: + case LengthModifier::AsInt3264: + case LengthModifier::AsWide: + return ArgType::Invalid(); + } + + // Unsigned int. + case ConversionSpecifier::oArg: + case ConversionSpecifier::OArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::UArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + switch (LM.getKind()) { + case LengthModifier::None: + return ArgType::PtrTo(Ctx.UnsignedIntTy); + case LengthModifier::AsChar: + return ArgType::PtrTo(Ctx.UnsignedCharTy); + case LengthModifier::AsShort: + return ArgType::PtrTo(Ctx.UnsignedShortTy); + case LengthModifier::AsLong: + return ArgType::PtrTo(Ctx.UnsignedLongTy); + case LengthModifier::AsLongLong: + case LengthModifier::AsQuad: + return ArgType::PtrTo(Ctx.UnsignedLongLongTy); + case LengthModifier::AsInt64: + return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")); + case LengthModifier::AsIntMax: + return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t")); + case LengthModifier::AsSizeT: + return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t")); + case LengthModifier::AsPtrDiff: + return ArgType::PtrTo( + ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); + case LengthModifier::AsLongDouble: + // GNU extension. + return ArgType::PtrTo(Ctx.UnsignedLongLongTy); + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + case LengthModifier::AsInt32: + case LengthModifier::AsInt3264: + case LengthModifier::AsWide: + return ArgType::Invalid(); + } + + // Float. + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + switch (LM.getKind()) { + case LengthModifier::None: + return ArgType::PtrTo(Ctx.FloatTy); + case LengthModifier::AsLong: + return ArgType::PtrTo(Ctx.DoubleTy); + case LengthModifier::AsLongDouble: + return ArgType::PtrTo(Ctx.LongDoubleTy); + default: + return ArgType::Invalid(); + } + + // Char, string and scanlist. + case ConversionSpecifier::cArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::ScanListArg: + switch (LM.getKind()) { + case LengthModifier::None: + return ArgType::PtrTo(ArgType::AnyCharTy); + case LengthModifier::AsLong: + case LengthModifier::AsWide: + return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t")); + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + return ArgType::PtrTo(ArgType::CStrTy); + case LengthModifier::AsShort: + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) + return ArgType::PtrTo(ArgType::AnyCharTy); + LLVM_FALLTHROUGH; + default: + return ArgType::Invalid(); + } + case ConversionSpecifier::CArg: + case ConversionSpecifier::SArg: + // FIXME: Mac OS X specific? + switch (LM.getKind()) { + case LengthModifier::None: + case LengthModifier::AsWide: + return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t")); + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *")); + case LengthModifier::AsShort: + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) + return ArgType::PtrTo(ArgType::AnyCharTy); + LLVM_FALLTHROUGH; + default: + return ArgType::Invalid(); + } + + // Pointer. + case ConversionSpecifier::pArg: + return ArgType::PtrTo(ArgType::CPointerTy); + + // Write-back. + case ConversionSpecifier::nArg: + switch (LM.getKind()) { + case LengthModifier::None: + return ArgType::PtrTo(Ctx.IntTy); + case LengthModifier::AsChar: + return ArgType::PtrTo(Ctx.SignedCharTy); + case LengthModifier::AsShort: + return ArgType::PtrTo(Ctx.ShortTy); + case LengthModifier::AsLong: + return ArgType::PtrTo(Ctx.LongTy); + case LengthModifier::AsLongLong: + case LengthModifier::AsQuad: + return ArgType::PtrTo(Ctx.LongLongTy); + case LengthModifier::AsInt64: + return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64")); + case LengthModifier::AsIntMax: + return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); + case LengthModifier::AsSizeT: + return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t")); + case LengthModifier::AsPtrDiff: + return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); + case LengthModifier::AsLongDouble: + return ArgType(); // FIXME: Is this a known extension? + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + case LengthModifier::AsInt32: + case LengthModifier::AsInt3264: + case LengthModifier::AsWide: + return ArgType::Invalid(); + } + + default: + break; + } + + return ArgType(); +} + +bool ScanfSpecifier::fixType(QualType QT, QualType RawQT, + const LangOptions &LangOpt, + ASTContext &Ctx) { + + // %n is different from other conversion specifiers; don't try to fix it. + if (CS.getKind() == ConversionSpecifier::nArg) + return false; + + if (!QT->isPointerType()) + return false; + + QualType PT = QT->getPointeeType(); + + // If it's an enum, get its underlying type. + if (const EnumType *ETy = PT->getAs<EnumType>()) { + // Don't try to fix incomplete enums. + if (!ETy->getDecl()->isComplete()) + return false; + PT = ETy->getDecl()->getIntegerType(); + } + + const BuiltinType *BT = PT->getAs<BuiltinType>(); + if (!BT) + return false; + + // Pointer to a character. + if (PT->isAnyCharacterType()) { + CS.setKind(ConversionSpecifier::sArg); + if (PT->isWideCharType()) + LM.setKind(LengthModifier::AsWideChar); + else + LM.setKind(LengthModifier::None); + + // If we know the target array length, we can use it as a field width. + if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) { + if (CAT->getSizeModifier() == ArrayType::Normal) + FieldWidth = OptionalAmount(OptionalAmount::Constant, + CAT->getSize().getZExtValue() - 1, + "", 0, false); + + } + return true; + } + + // Figure out the length modifier. + switch (BT->getKind()) { + // no modifier + case BuiltinType::UInt: + case BuiltinType::Int: + case BuiltinType::Float: + LM.setKind(LengthModifier::None); + break; + + // hh + case BuiltinType::Char_U: + case BuiltinType::UChar: + case BuiltinType::Char_S: + case BuiltinType::SChar: + LM.setKind(LengthModifier::AsChar); + break; + + // h + case BuiltinType::Short: + case BuiltinType::UShort: + LM.setKind(LengthModifier::AsShort); + break; + + // l + case BuiltinType::Long: + case BuiltinType::ULong: + case BuiltinType::Double: + LM.setKind(LengthModifier::AsLong); + break; + + // ll + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + LM.setKind(LengthModifier::AsLongLong); + break; + + // L + case BuiltinType::LongDouble: + LM.setKind(LengthModifier::AsLongDouble); + break; + + // Don't know. + default: + return false; + } + + // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. + if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) + namedTypeToLengthModifier(PT, LM); + + // If fixing the length modifier was enough, we are done. + if (hasValidLengthModifier(Ctx.getTargetInfo())) { + const analyze_scanf::ArgType &AT = getArgType(Ctx); + if (AT.isValid() && AT.matchesType(Ctx, QT)) + return true; + } + + // Figure out the conversion specifier. + if (PT->isRealFloatingType()) + CS.setKind(ConversionSpecifier::fArg); + else if (PT->isSignedIntegerType()) + CS.setKind(ConversionSpecifier::dArg); + else if (PT->isUnsignedIntegerType()) + CS.setKind(ConversionSpecifier::uArg); + else + llvm_unreachable("Unexpected type"); + + return true; +} + +void ScanfSpecifier::toString(raw_ostream &os) const { + os << "%"; + + if (usesPositionalArg()) + os << getPositionalArgIndex() << "$"; + if (SuppressAssignment) + os << "*"; + + FieldWidth.toString(os); + os << LM.toString(); + os << CS.toString(); +} + +bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H, + const char *I, + const char *E, + const LangOptions &LO, + const TargetInfo &Target) { + + unsigned argIndex = 0; + + // Keep looking for a format specifier until we have exhausted the string. + while (I != E) { + const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex, + LO, Target); + // Did a fail-stop error of any kind occur when parsing the specifier? + // If so, don't do any more processing. + if (FSR.shouldStop()) + return true; + // Did we exhaust the string or encounter an error that + // we can recover from? + if (!FSR.hasValue()) + continue; + // We have a format specifier. Pass it to the callback. + if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(), + I - FSR.getStart())) { + return true; + } + } + assert(I == E && "Format string not exhausted"); + return false; +} diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index b03b3a6837..116291bfa1 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -76,6 +76,14 @@ const char *Stmt::getStmtClassName() const { return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name; } +// Check that no statement / expression class is polymorphic. LLVM style RTTI +// should be used instead. If absolutely needed an exception can still be added +// here by defining the appropriate macro (but please don't do this). +#define STMT(CLASS, PARENT) \ + static_assert(!std::is_polymorphic<CLASS>::value, \ + #CLASS " should not be polymorphic!"); +#include "clang/AST/StmtNodes.inc" + void Stmt::PrintStats() { // Ensure the table is primed. getStmtInfoTableEntry(Stmt::NullStmtClass); @@ -118,8 +126,8 @@ Stmt *Stmt::IgnoreImplicit() { while (s != lasts) { lasts = s; - if (auto *ewc = dyn_cast<ExprWithCleanups>(s)) - s = ewc->getSubExpr(); + if (auto *fe = dyn_cast<FullExpr>(s)) + s = fe->getSubExpr(); if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s)) s = mte->GetTemporaryExpr(); @@ -303,17 +311,15 @@ SourceLocation Stmt::getEndLoc() const { } int64_t Stmt::getID(const ASTContext &Context) const { - Optional<int64_t> Out = Context.getAllocator().identifyObject(this); - assert(Out && "Wrong allocator used"); - assert(*Out % alignof(Stmt) == 0 && "Wrong alignment information"); - return *Out / alignof(Stmt); + return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this); } CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, SourceLocation RB) - : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) { + : Stmt(CompoundStmtClass), RBraceLoc(RB) { CompoundStmtBits.NumStmts = Stmts.size(); setStmts(Stmts); + CompoundStmtBits.LBraceLoc = LB; } void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) { @@ -798,51 +804,99 @@ void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr, }); } -IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, bool IsConstexpr, - Stmt *init, VarDecl *var, Expr *cond, Stmt *then, - SourceLocation EL, Stmt *elsev) - : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) { +IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, + Stmt *Init, VarDecl *Var, Expr *Cond, Stmt *Then, + SourceLocation EL, Stmt *Else) + : Stmt(IfStmtClass) { + bool HasElse = Else != nullptr; + bool HasVar = Var != nullptr; + bool HasInit = Init != nullptr; + IfStmtBits.HasElse = HasElse; + IfStmtBits.HasVar = HasVar; + IfStmtBits.HasInit = HasInit; + setConstexpr(IsConstexpr); - setConditionVariable(C, var); - SubExprs[INIT] = init; - SubExprs[COND] = cond; - SubExprs[THEN] = then; - SubExprs[ELSE] = elsev; -} -VarDecl *IfStmt::getConditionVariable() const { - if (!SubExprs[VAR]) + setCond(Cond); + setThen(Then); + if (HasElse) + setElse(Else); + if (HasVar) + setConditionVariable(Ctx, Var); + if (HasInit) + setInit(Init); + + setIfLoc(IL); + if (HasElse) + setElseLoc(EL); +} + +IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit) + : Stmt(IfStmtClass, Empty) { + IfStmtBits.HasElse = HasElse; + IfStmtBits.HasVar = HasVar; + IfStmtBits.HasInit = HasInit; +} + +IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL, + bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond, + Stmt *Then, SourceLocation EL, Stmt *Else) { + bool HasElse = Else != nullptr; + bool HasVar = Var != nullptr; + bool HasInit = Init != nullptr; + void *Mem = Ctx.Allocate( + totalSizeToAlloc<Stmt *, SourceLocation>( + NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), + alignof(IfStmt)); + return new (Mem) + IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, Then, EL, Else); +} + +IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar, + bool HasInit) { + void *Mem = Ctx.Allocate( + totalSizeToAlloc<Stmt *, SourceLocation>( + NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), + alignof(IfStmt)); + return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit); +} + +VarDecl *IfStmt::getConditionVariable() { + auto *DS = getConditionVariableDeclStmt(); + if (!DS) return nullptr; - - auto *DS = cast<DeclStmt>(SubExprs[VAR]); return cast<VarDecl>(DS->getSingleDecl()); } -void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { +void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { + assert(hasVarStorage() && + "This if statement has no storage for a condition variable!"); + if (!V) { - SubExprs[VAR] = nullptr; + getTrailingObjects<Stmt *>()[varOffset()] = nullptr; return; } SourceRange VarRange = V->getSourceRange(); - SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), - VarRange.getEnd()); + getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) + DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } bool IfStmt::isObjCAvailabilityCheck() const { - return isa<ObjCAvailabilityCheckExpr>(SubExprs[COND]); + return isa<ObjCAvailabilityCheckExpr>(getCond()); } ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP) - : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP) + : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP) { SubExprs[INIT] = Init; setConditionVariable(C, condVar); SubExprs[COND] = Cond; SubExprs[INC] = Inc; SubExprs[BODY] = Body; + ForStmtBits.ForLoc = FL; } VarDecl *ForStmt::getConditionVariable() const { @@ -864,66 +918,125 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { VarRange.getEnd()); } -SwitchStmt::SwitchStmt(const ASTContext &C, Stmt *init, VarDecl *Var, - Expr *cond) - : Stmt(SwitchStmtClass), FirstCase(nullptr, false) { - setConditionVariable(C, Var); - SubExprs[INIT] = init; - SubExprs[COND] = cond; - SubExprs[BODY] = nullptr; +SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, + Expr *Cond) + : Stmt(SwitchStmtClass), FirstCase(nullptr) { + bool HasInit = Init != nullptr; + bool HasVar = Var != nullptr; + SwitchStmtBits.HasInit = HasInit; + SwitchStmtBits.HasVar = HasVar; + SwitchStmtBits.AllEnumCasesCovered = false; + + setCond(Cond); + setBody(nullptr); + if (HasInit) + setInit(Init); + if (HasVar) + setConditionVariable(Ctx, Var); + + setSwitchLoc(SourceLocation{}); } -VarDecl *SwitchStmt::getConditionVariable() const { - if (!SubExprs[VAR]) - return nullptr; +SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar) + : Stmt(SwitchStmtClass, Empty) { + SwitchStmtBits.HasInit = HasInit; + SwitchStmtBits.HasVar = HasVar; + SwitchStmtBits.AllEnumCasesCovered = false; +} + +SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, + Expr *Cond) { + bool HasInit = Init != nullptr; + bool HasVar = Var != nullptr; + void *Mem = Ctx.Allocate( + totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), + alignof(SwitchStmt)); + return new (Mem) SwitchStmt(Ctx, Init, Var, Cond); +} + +SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit, + bool HasVar) { + void *Mem = Ctx.Allocate( + totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), + alignof(SwitchStmt)); + return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar); +} - auto *DS = cast<DeclStmt>(SubExprs[VAR]); +VarDecl *SwitchStmt::getConditionVariable() { + auto *DS = getConditionVariableDeclStmt(); + if (!DS) + return nullptr; return cast<VarDecl>(DS->getSingleDecl()); } -void SwitchStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { +void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { + assert(hasVarStorage() && + "This switch statement has no storage for a condition variable!"); + if (!V) { - SubExprs[VAR] = nullptr; + getTrailingObjects<Stmt *>()[varOffset()] = nullptr; return; } SourceRange VarRange = V->getSourceRange(); - SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), - VarRange.getEnd()); + getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) + DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } -Stmt *SwitchCase::getSubStmt() { - if (isa<CaseStmt>(this)) - return cast<CaseStmt>(this)->getSubStmt(); - return cast<DefaultStmt>(this)->getSubStmt(); +WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, + Stmt *Body, SourceLocation WL) + : Stmt(WhileStmtClass) { + bool HasVar = Var != nullptr; + WhileStmtBits.HasVar = HasVar; + + setCond(Cond); + setBody(Body); + if (HasVar) + setConditionVariable(Ctx, Var); + + setWhileLoc(WL); } -WhileStmt::WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, - SourceLocation WL) - : Stmt(WhileStmtClass) { - setConditionVariable(C, Var); - SubExprs[COND] = cond; - SubExprs[BODY] = body; - WhileLoc = WL; +WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar) + : Stmt(WhileStmtClass, Empty) { + WhileStmtBits.HasVar = HasVar; } -VarDecl *WhileStmt::getConditionVariable() const { - if (!SubExprs[VAR]) - return nullptr; +WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, + Stmt *Body, SourceLocation WL) { + bool HasVar = Var != nullptr; + void *Mem = + Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), + alignof(WhileStmt)); + return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL); +} + +WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) { + void *Mem = + Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), + alignof(WhileStmt)); + return new (Mem) WhileStmt(EmptyShell(), HasVar); +} - auto *DS = cast<DeclStmt>(SubExprs[VAR]); +VarDecl *WhileStmt::getConditionVariable() { + auto *DS = getConditionVariableDeclStmt(); + if (!DS) + return nullptr; return cast<VarDecl>(DS->getSingleDecl()); } -void WhileStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { +void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { + assert(hasVarStorage() && + "This while statement has no storage for a condition variable!"); + if (!V) { - SubExprs[VAR] = nullptr; + getTrailingObjects<Stmt *>()[varOffset()] = nullptr; return; } SourceRange VarRange = V->getSourceRange(); - SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), - VarRange.getEnd()); + getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) + DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } // IndirectGotoStmt @@ -934,11 +1047,54 @@ LabelDecl *IndirectGotoStmt::getConstantTarget() { } // ReturnStmt -const Expr* ReturnStmt::getRetValue() const { - return cast_or_null<Expr>(RetExpr); -} -Expr* ReturnStmt::getRetValue() { - return cast_or_null<Expr>(RetExpr); +ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) + : Stmt(ReturnStmtClass), RetExpr(E) { + bool HasNRVOCandidate = NRVOCandidate != nullptr; + ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; + if (HasNRVOCandidate) + setNRVOCandidate(NRVOCandidate); + setReturnLoc(RL); +} + +ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate) + : Stmt(ReturnStmtClass, Empty) { + ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; +} + +ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL, + Expr *E, const VarDecl *NRVOCandidate) { + bool HasNRVOCandidate = NRVOCandidate != nullptr; + void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), + alignof(ReturnStmt)); + return new (Mem) ReturnStmt(RL, E, NRVOCandidate); +} + +ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx, + bool HasNRVOCandidate) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), + alignof(ReturnStmt)); + return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate); +} + +// CaseStmt +CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs, + SourceLocation caseLoc, SourceLocation ellipsisLoc, + SourceLocation colonLoc) { + bool CaseStmtIsGNURange = rhs != nullptr; + void *Mem = Ctx.Allocate( + totalSizeToAlloc<Stmt *, SourceLocation>( + NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), + alignof(CaseStmt)); + return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc); +} + +CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx, + bool CaseStmtIsGNURange) { + void *Mem = Ctx.Allocate( + totalSizeToAlloc<Stmt *, SourceLocation>( + NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), + alignof(CaseStmt)); + return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange); } SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp index 1258af7a2d..85a2daa080 100644 --- a/lib/AST/StmtOpenMP.cpp +++ b/lib/AST/StmtOpenMP.cpp @@ -1079,6 +1079,8 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond); + Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond); Dir->HasCancel = HasCancel; return Dir; } @@ -1145,6 +1147,8 @@ OMPDistributeParallelForSimdDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond); + Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond); return Dir; } @@ -1457,6 +1461,8 @@ OMPTeamsDistributeParallelForSimdDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond); + Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond); return Dir; } @@ -1524,6 +1530,8 @@ OMPTeamsDistributeParallelForDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond); + Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond); Dir->HasCancel = HasCancel; return Dir; } @@ -1670,6 +1678,8 @@ OMPTargetTeamsDistributeParallelForDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond); + Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond); Dir->HasCancel = HasCancel; return Dir; } @@ -1741,6 +1751,8 @@ OMPTargetTeamsDistributeParallelForSimdDirective::Create( Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond); + Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond); return Dir; } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 51591953e7..ae726e3871 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -622,443 +622,6 @@ void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) { } //===----------------------------------------------------------------------===// -// OpenMP clauses printing methods -//===----------------------------------------------------------------------===// - -namespace { - -class OMPClausePrinter : public OMPClauseVisitor<OMPClausePrinter> { - raw_ostream &OS; - const PrintingPolicy &Policy; - - /// Process clauses with list of variables. - template <typename T> - void VisitOMPClauseList(T *Node, char StartSym); - -public: - OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy) - : OS(OS), Policy(Policy) {} - -#define OPENMP_CLAUSE(Name, Class) \ - void Visit##Class(Class *S); -#include "clang/Basic/OpenMPKinds.def" -}; - -} // namespace - -void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) { - OS << "if("; - if (Node->getNameModifier() != OMPD_unknown) - OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": "; - Node->getCondition()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) { - OS << "final("; - Node->getCondition()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) { - OS << "num_threads("; - Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) { - OS << "safelen("; - Node->getSafelen()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) { - OS << "simdlen("; - Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) { - OS << "collapse("; - Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) { - OS << "default(" - << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind()) - << ")"; -} - -void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) { - OS << "proc_bind(" - << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind()) - << ")"; -} - -void OMPClausePrinter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) { - OS << "unified_address"; -} - -void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { - OS << "schedule("; - if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { - OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, - Node->getFirstScheduleModifier()); - if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { - OS << ", "; - OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, - Node->getSecondScheduleModifier()); - } - OS << ": "; - } - OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind()); - if (auto *E = Node->getChunkSize()) { - OS << ", "; - E->printPretty(OS, nullptr, Policy); - } - OS << ")"; -} - -void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) { - OS << "ordered"; - if (auto *Num = Node->getNumForLoops()) { - OS << "("; - Num->printPretty(OS, nullptr, Policy, 0); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) { - OS << "nowait"; -} - -void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) { - OS << "untied"; -} - -void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) { - OS << "nogroup"; -} - -void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) { - OS << "mergeable"; -} - -void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; } - -void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; } - -void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) { - OS << "update"; -} - -void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) { - OS << "capture"; -} - -void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) { - OS << "seq_cst"; -} - -void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) { - OS << "threads"; -} - -void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; } - -void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) { - OS << "device("; - Node->getDevice()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) { - OS << "num_teams("; - Node->getNumTeams()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) { - OS << "thread_limit("; - Node->getThreadLimit()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) { - OS << "priority("; - Node->getPriority()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) { - OS << "grainsize("; - Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) { - OS << "num_tasks("; - Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) { - OS << "hint("; - Node->getHint()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; -} - -template<typename T> -void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { - for (typename T::varlist_iterator I = Node->varlist_begin(), - E = Node->varlist_end(); - I != E; ++I) { - assert(*I && "Expected non-null Stmt"); - OS << (I == Node->varlist_begin() ? StartSym : ','); - if (auto *DRE = dyn_cast<DeclRefExpr>(*I)) { - if (isa<OMPCapturedExprDecl>(DRE->getDecl())) - DRE->printPretty(OS, nullptr, Policy, 0); - else - DRE->getDecl()->printQualifiedName(OS); - } else - (*I)->printPretty(OS, nullptr, Policy, 0); - } -} - -void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) { - if (!Node->varlist_empty()) { - OS << "private"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) { - if (!Node->varlist_empty()) { - OS << "firstprivate"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) { - if (!Node->varlist_empty()) { - OS << "lastprivate"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) { - if (!Node->varlist_empty()) { - OS << "shared"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) { - if (!Node->varlist_empty()) { - OS << "reduction("; - NestedNameSpecifier *QualifierLoc = - Node->getQualifierLoc().getNestedNameSpecifier(); - OverloadedOperatorKind OOK = - Node->getNameInfo().getName().getCXXOverloadedOperator(); - if (QualifierLoc == nullptr && OOK != OO_None) { - // Print reduction identifier in C format - OS << getOperatorSpelling(OOK); - } else { - // Use C++ format - if (QualifierLoc != nullptr) - QualifierLoc->print(OS, Policy); - OS << Node->getNameInfo(); - } - OS << ":"; - VisitOMPClauseList(Node, ' '); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPTaskReductionClause( - OMPTaskReductionClause *Node) { - if (!Node->varlist_empty()) { - OS << "task_reduction("; - NestedNameSpecifier *QualifierLoc = - Node->getQualifierLoc().getNestedNameSpecifier(); - OverloadedOperatorKind OOK = - Node->getNameInfo().getName().getCXXOverloadedOperator(); - if (QualifierLoc == nullptr && OOK != OO_None) { - // Print reduction identifier in C format - OS << getOperatorSpelling(OOK); - } else { - // Use C++ format - if (QualifierLoc != nullptr) - QualifierLoc->print(OS, Policy); - OS << Node->getNameInfo(); - } - OS << ":"; - VisitOMPClauseList(Node, ' '); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) { - if (!Node->varlist_empty()) { - OS << "in_reduction("; - NestedNameSpecifier *QualifierLoc = - Node->getQualifierLoc().getNestedNameSpecifier(); - OverloadedOperatorKind OOK = - Node->getNameInfo().getName().getCXXOverloadedOperator(); - if (QualifierLoc == nullptr && OOK != OO_None) { - // Print reduction identifier in C format - OS << getOperatorSpelling(OOK); - } else { - // Use C++ format - if (QualifierLoc != nullptr) - QualifierLoc->print(OS, Policy); - OS << Node->getNameInfo(); - } - OS << ":"; - VisitOMPClauseList(Node, ' '); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { - if (!Node->varlist_empty()) { - OS << "linear"; - if (Node->getModifierLoc().isValid()) { - OS << '(' - << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier()); - } - VisitOMPClauseList(Node, '('); - if (Node->getModifierLoc().isValid()) - OS << ')'; - if (Node->getStep() != nullptr) { - OS << ": "; - Node->getStep()->printPretty(OS, nullptr, Policy, 0); - } - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) { - if (!Node->varlist_empty()) { - OS << "aligned"; - VisitOMPClauseList(Node, '('); - if (Node->getAlignment() != nullptr) { - OS << ": "; - Node->getAlignment()->printPretty(OS, nullptr, Policy, 0); - } - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) { - if (!Node->varlist_empty()) { - OS << "copyin"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) { - if (!Node->varlist_empty()) { - OS << "copyprivate"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) { - if (!Node->varlist_empty()) { - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) { - OS << "depend("; - OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), - Node->getDependencyKind()); - if (!Node->varlist_empty()) { - OS << " :"; - VisitOMPClauseList(Node, ' '); - } - OS << ")"; -} - -void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) { - if (!Node->varlist_empty()) { - OS << "map("; - if (Node->getMapType() != OMPC_MAP_unknown) { - if (Node->getMapTypeModifier() != OMPC_MAP_unknown) { - OS << getOpenMPSimpleClauseTypeName(OMPC_map, - Node->getMapTypeModifier()); - OS << ','; - } - OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType()); - OS << ':'; - } - VisitOMPClauseList(Node, ' '); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) { - if (!Node->varlist_empty()) { - OS << "to"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) { - if (!Node->varlist_empty()) { - OS << "from"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) { - OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName( - OMPC_dist_schedule, Node->getDistScheduleKind()); - if (auto *E = Node->getChunkSize()) { - OS << ", "; - E->printPretty(OS, nullptr, Policy); - } - OS << ")"; -} - -void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) { - OS << "defaultmap("; - OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap, - Node->getDefaultmapModifier()); - OS << ": "; - OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap, - Node->getDefaultmapKind()); - OS << ")"; -} - -void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) { - if (!Node->varlist_empty()) { - OS << "use_device_ptr"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) { - if (!Node->varlist_empty()) { - OS << "is_device_ptr"; - VisitOMPClauseList(Node, '('); - OS << ")"; - } -} - -//===----------------------------------------------------------------------===// // OpenMP directives printing methods //===----------------------------------------------------------------------===// @@ -1343,6 +906,10 @@ void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective( // Expr printing methods. //===----------------------------------------------------------------------===// +void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) { + PrintExpr(Node->getSubExpr()); +} + void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) { OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy); @@ -1428,7 +995,7 @@ void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) { } void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) { - OS << PredefinedExpr::getIdentTypeName(Node->getIdentType()); + OS << PredefinedExpr::getIdentKindName(Node->getIdentKind()); } void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { @@ -1672,6 +1239,9 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){ else OS << "__alignof"; break; + case UETT_PreferredAlignOf: + OS << "__alignof"; + break; case UETT_VecStep: OS << "vec_step"; break; diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index b97812345b..ec4dac03d4 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -470,6 +470,18 @@ void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { } void OMPClauseProfiler::VisitOMPUnifiedAddressClause( const OMPUnifiedAddressClause *C) {} +void OMPClauseProfiler::VisitOMPUnifiedSharedMemoryClause( + const OMPUnifiedSharedMemoryClause *C) {} + +void OMPClauseProfiler::VisitOMPReverseOffloadClause( + const OMPReverseOffloadClause *C) {} + +void OMPClauseProfiler::VisitOMPDynamicAllocatorsClause( + const OMPDynamicAllocatorsClause *C) {} + +void OMPClauseProfiler::VisitOMPAtomicDefaultMemOrderClause( + const OMPAtomicDefaultMemOrderClause *C) {} + void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) { VistOMPClauseWithPreInit(C); if (auto *S = C->getChunkSize()) @@ -987,6 +999,10 @@ void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } +void StmtProfiler::VisitConstantExpr(const ConstantExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) { VisitExpr(S); if (!Canonical) @@ -1001,7 +1017,7 @@ void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) { void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) { VisitExpr(S); - ID.AddInteger(S->getIdentType()); + ID.AddInteger(S->getIdentKind()); } void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) { diff --git a/lib/AST/TextNodeDumper.cpp b/lib/AST/TextNodeDumper.cpp new file mode 100644 index 0000000000..27d8f25393 --- /dev/null +++ b/lib/AST/TextNodeDumper.cpp @@ -0,0 +1,285 @@ +//===--- TextNodeDumper.cpp - Printing of AST nodes -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements AST dumping of components of individual AST nodes. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/TextNodeDumper.h" + +using namespace clang; + +TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors, + const SourceManager *SM, + const PrintingPolicy &PrintPolicy, + const comments::CommandTraits *Traits) + : OS(OS), ShowColors(ShowColors), SM(SM), PrintPolicy(PrintPolicy), + Traits(Traits) {} + +void TextNodeDumper::Visit(const comments::Comment *C, + const comments::FullComment *FC) { + if (!C) { + ColorScope Color(OS, ShowColors, NullColor); + OS << "<<<NULL>>>"; + return; + } + + { + ColorScope Color(OS, ShowColors, CommentColor); + OS << C->getCommentKindName(); + } + dumpPointer(C); + dumpSourceRange(C->getSourceRange()); + + ConstCommentVisitor<TextNodeDumper, void, + const comments::FullComment *>::visit(C, FC); +} + +void TextNodeDumper::dumpPointer(const void *Ptr) { + ColorScope Color(OS, ShowColors, AddressColor); + OS << ' ' << Ptr; +} + +void TextNodeDumper::dumpLocation(SourceLocation Loc) { + if (!SM) + return; + + ColorScope Color(OS, ShowColors, LocationColor); + SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); + + // The general format we print out is filename:line:col, but we drop pieces + // that haven't changed since the last loc printed. + PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); + + if (PLoc.isInvalid()) { + OS << "<invalid sloc>"; + return; + } + + if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { + OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':' + << PLoc.getColumn(); + LastLocFilename = PLoc.getFilename(); + LastLocLine = PLoc.getLine(); + } else if (PLoc.getLine() != LastLocLine) { + OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); + LastLocLine = PLoc.getLine(); + } else { + OS << "col" << ':' << PLoc.getColumn(); + } +} + +void TextNodeDumper::dumpSourceRange(SourceRange R) { + // Can't translate locations if a SourceManager isn't available. + if (!SM) + return; + + OS << " <"; + dumpLocation(R.getBegin()); + if (R.getBegin() != R.getEnd()) { + OS << ", "; + dumpLocation(R.getEnd()); + } + OS << ">"; + + // <t2.c:123:421[blah], t2.c:412:321> +} + +void TextNodeDumper::dumpBareType(QualType T, bool Desugar) { + ColorScope Color(OS, ShowColors, TypeColor); + + SplitQualType T_split = T.split(); + OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'"; + + if (Desugar && !T.isNull()) { + // If the type is sugared, also dump a (shallow) desugared type. + SplitQualType D_split = T.getSplitDesugaredType(); + if (T_split != D_split) + OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'"; + } +} + +void TextNodeDumper::dumpType(QualType T) { + OS << ' '; + dumpBareType(T); +} + +void TextNodeDumper::dumpBareDeclRef(const Decl *D) { + if (!D) { + ColorScope Color(OS, ShowColors, NullColor); + OS << "<<<NULL>>>"; + return; + } + + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << D->getDeclKindName(); + } + dumpPointer(D); + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + ColorScope Color(OS, ShowColors, DeclNameColor); + OS << " '" << ND->getDeclName() << '\''; + } + + if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) + dumpType(VD->getType()); +} + +void TextNodeDumper::dumpName(const NamedDecl *ND) { + if (ND->getDeclName()) { + ColorScope Color(OS, ShowColors, DeclNameColor); + OS << ' ' << ND->getNameAsString(); + } +} + +void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) { + switch (AS) { + case AS_none: + break; + case AS_public: + OS << "public"; + break; + case AS_protected: + OS << "protected"; + break; + case AS_private: + OS << "private"; + break; + } +} + +void TextNodeDumper::dumpCXXTemporary(const CXXTemporary *Temporary) { + OS << "(CXXTemporary"; + dumpPointer(Temporary); + OS << ")"; +} + +const char *TextNodeDumper::getCommandName(unsigned CommandID) { + if (Traits) + return Traits->getCommandInfo(CommandID)->Name; + const comments::CommandInfo *Info = + comments::CommandTraits::getBuiltinCommandInfo(CommandID); + if (Info) + return Info->Name; + return "<not a builtin command>"; +} + +void TextNodeDumper::visitTextComment(const comments::TextComment *C, + const comments::FullComment *) { + OS << " Text=\"" << C->getText() << "\""; +} + +void TextNodeDumper::visitInlineCommandComment( + const comments::InlineCommandComment *C, const comments::FullComment *) { + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; + switch (C->getRenderKind()) { + case comments::InlineCommandComment::RenderNormal: + OS << " RenderNormal"; + break; + case comments::InlineCommandComment::RenderBold: + OS << " RenderBold"; + break; + case comments::InlineCommandComment::RenderMonospaced: + OS << " RenderMonospaced"; + break; + case comments::InlineCommandComment::RenderEmphasized: + OS << " RenderEmphasized"; + break; + } + + for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) + OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; +} + +void TextNodeDumper::visitHTMLStartTagComment( + const comments::HTMLStartTagComment *C, const comments::FullComment *) { + OS << " Name=\"" << C->getTagName() << "\""; + if (C->getNumAttrs() != 0) { + OS << " Attrs: "; + for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) { + const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(i); + OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\""; + } + } + if (C->isSelfClosing()) + OS << " SelfClosing"; +} + +void TextNodeDumper::visitHTMLEndTagComment( + const comments::HTMLEndTagComment *C, const comments::FullComment *) { + OS << " Name=\"" << C->getTagName() << "\""; +} + +void TextNodeDumper::visitBlockCommandComment( + const comments::BlockCommandComment *C, const comments::FullComment *) { + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; + for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) + OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; +} + +void TextNodeDumper::visitParamCommandComment( + const comments::ParamCommandComment *C, const comments::FullComment *FC) { + OS << " " + << comments::ParamCommandComment::getDirectionAsString(C->getDirection()); + + if (C->isDirectionExplicit()) + OS << " explicitly"; + else + OS << " implicitly"; + + if (C->hasParamName()) { + if (C->isParamIndexValid()) + OS << " Param=\"" << C->getParamName(FC) << "\""; + else + OS << " Param=\"" << C->getParamNameAsWritten() << "\""; + } + + if (C->isParamIndexValid() && !C->isVarArgParam()) + OS << " ParamIndex=" << C->getParamIndex(); +} + +void TextNodeDumper::visitTParamCommandComment( + const comments::TParamCommandComment *C, const comments::FullComment *FC) { + if (C->hasParamName()) { + if (C->isPositionValid()) + OS << " Param=\"" << C->getParamName(FC) << "\""; + else + OS << " Param=\"" << C->getParamNameAsWritten() << "\""; + } + + if (C->isPositionValid()) { + OS << " Position=<"; + for (unsigned i = 0, e = C->getDepth(); i != e; ++i) { + OS << C->getIndex(i); + if (i != e - 1) + OS << ", "; + } + OS << ">"; + } +} + +void TextNodeDumper::visitVerbatimBlockComment( + const comments::VerbatimBlockComment *C, const comments::FullComment *) { + OS << " Name=\"" << getCommandName(C->getCommandID()) + << "\"" + " CloseName=\"" + << C->getCloseName() << "\""; +} + +void TextNodeDumper::visitVerbatimBlockLineComment( + const comments::VerbatimBlockLineComment *C, + const comments::FullComment *) { + OS << " Text=\"" << C->getText() << "\""; +} + +void TextNodeDumper::visitVerbatimLineComment( + const comments::VerbatimLineComment *C, const comments::FullComment *) { + OS << " Text=\"" << C->getText() << "\""; +} diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 2e1aed26fd..0dbc88c045 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -291,6 +291,14 @@ QualType QualType::getSingleStepDesugaredTypeImpl(QualType type, return Context.getQualifiedType(desugar, split.Quals); } +// Check that no type class is polymorphic. LLVM style RTTI should be used +// instead. If absolutely needed an exception can still be added here by +// defining the appropriate macro (but please don't do this). +#define TYPE(CLASS, BASE) \ + static_assert(!std::is_polymorphic<CLASS##Type>::value, \ + #CLASS "Type should not be polymorphic!"); +#include "clang/AST/TypeNodes.def" + QualType Type::getLocallyUnqualifiedSingleStepDesugaredType() const { switch (getTypeClass()) { #define ABSTRACT_TYPE(Class, Parent) @@ -1965,6 +1973,7 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer; if (BT->isInteger()) return STK_Integral; if (BT->isFloatingPoint()) return STK_Floating; + if (BT->isFixedPointType()) return STK_FixedPoint; llvm_unreachable("unknown scalar builtin type"); } else if (isa<PointerType>(T)) { return STK_CPointer; @@ -2785,6 +2794,10 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { return "reserve_id_t"; case OMPArraySection: return "<OpenMP array section type>"; +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case Id: \ + return #ExtType; +#include "clang/Basic/OpenCLExtensionTypes.def" } llvm_unreachable("Invalid builtin type."); @@ -2819,6 +2832,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86RegCall : return "regcall"; case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; + case CC_AArch64VectorCall: return "aarch64_vector_pcs"; case CC_IntelOclBicc: return "intel_ocl_bicc"; case CC_SpirFunction: return "spir_function"; case CC_OpenCLKernel: return "opencl_kernel"; @@ -2833,24 +2847,28 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, QualType canonical, const ExtProtoInfo &epi) - : FunctionType(FunctionProto, result, canonical, - result->isDependentType(), + : FunctionType(FunctionProto, result, canonical, result->isDependentType(), result->isInstantiationDependentType(), result->isVariablyModifiedType(), - result->containsUnexpandedParameterPack(), epi.ExtInfo), - NumParams(params.size()), - NumExceptions(epi.ExceptionSpec.Exceptions.size()), - ExceptionSpecType(epi.ExceptionSpec.Type), - HasExtParameterInfos(epi.ExtParameterInfos != nullptr), - Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) { - assert(NumParams == params.size() && "function has too many parameters"); - - FunctionTypeBits.TypeQuals = epi.TypeQuals; + result->containsUnexpandedParameterPack(), epi.ExtInfo) { + FunctionTypeBits.FastTypeQuals = epi.TypeQuals.getFastQualifiers(); FunctionTypeBits.RefQualifier = epi.RefQualifier; + FunctionTypeBits.NumParams = params.size(); + assert(getNumParams() == params.size() && "NumParams overflow!"); + FunctionTypeBits.ExceptionSpecType = epi.ExceptionSpec.Type; + FunctionTypeBits.HasExtParameterInfos = !!epi.ExtParameterInfos; + FunctionTypeBits.Variadic = epi.Variadic; + FunctionTypeBits.HasTrailingReturn = epi.HasTrailingReturn; + + // Fill in the extra trailing bitfields if present. + if (hasExtraBitfields(epi.ExceptionSpec.Type)) { + auto &ExtraBits = *getTrailingObjects<FunctionTypeExtraBitfields>(); + ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size(); + } // Fill in the trailing argument array. - auto *argSlot = reinterpret_cast<QualType *>(this+1); - for (unsigned i = 0; i != NumParams; ++i) { + auto *argSlot = getTrailingObjects<QualType>(); + for (unsigned i = 0; i != getNumParams(); ++i) { if (params[i]->isDependentType()) setDependent(); else if (params[i]->isInstantiationDependentType()) @@ -2862,9 +2880,11 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, argSlot[i] = params[i]; } + // Fill in the exception type array if present. if (getExceptionSpecType() == EST_Dynamic) { - // Fill in the exception array. - QualType *exnSlot = argSlot + NumParams; + assert(hasExtraBitfields() && "missing trailing extra bitfields!"); + auto *exnSlot = + reinterpret_cast<QualType *>(getTrailingObjects<ExceptionType>()); unsigned I = 0; for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) { // Note that, before C++17, a dependent exception specification does @@ -2878,14 +2898,15 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, exnSlot[I++] = ExceptionType; } - } else if (isComputedNoexcept(getExceptionSpecType())) { + } + // Fill in the Expr * in the exception specification if present. + else if (isComputedNoexcept(getExceptionSpecType())) { assert(epi.ExceptionSpec.NoexceptExpr && "computed noexcept with no expr"); assert((getExceptionSpecType() == EST_DependentNoexcept) == epi.ExceptionSpec.NoexceptExpr->isValueDependent()); // Store the noexcept expression and context. - auto **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams); - *noexSlot = epi.ExceptionSpec.NoexceptExpr; + *getTrailingObjects<Expr *>() = epi.ExceptionSpec.NoexceptExpr; if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() || epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent()) @@ -2893,10 +2914,12 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - } else if (getExceptionSpecType() == EST_Uninstantiated) { + } + // Fill in the FunctionDecl * in the exception specification if present. + else if (getExceptionSpecType() == EST_Uninstantiated) { // Store the function decl from which we will resolve our // exception specification. - auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams); + auto **slot = getTrailingObjects<FunctionDecl *>(); slot[0] = epi.ExceptionSpec.SourceDecl; slot[1] = epi.ExceptionSpec.SourceTemplate; // This exception specification doesn't make the type dependent, because @@ -2904,7 +2927,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, } else if (getExceptionSpecType() == EST_Unevaluated) { // Store the function decl from which we will resolve our // exception specification. - auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams); + auto **slot = getTrailingObjects<FunctionDecl *>(); slot[0] = epi.ExceptionSpec.SourceDecl; } @@ -2921,12 +2944,19 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, setDependent(); } + // Fill in the extra parameter info if present. if (epi.ExtParameterInfos) { - auto *extParamInfos = - const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer()); - for (unsigned i = 0; i != NumParams; ++i) + auto *extParamInfos = getTrailingObjects<ExtParameterInfo>(); + for (unsigned i = 0; i != getNumParams(); ++i) extParamInfos[i] = epi.ExtParameterInfos[i]; } + + if (epi.TypeQuals.hasNonFastQualifiers()) { + FunctionTypeBits.HasExtQuals = 1; + *getTrailingObjects<Qualifiers>() = epi.TypeQuals; + } else { + FunctionTypeBits.HasExtQuals = 0; + } } bool FunctionProtoType::hasDependentExceptionSpec() const { @@ -2970,7 +3000,7 @@ CanThrowResult FunctionProtoType::canThrow() const { case EST_Dynamic: // 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) + for (unsigned I = 0; I != getNumExceptions(); ++I) if (!getExceptionType(I)->getAs<PackExpansionType>()) return CT_Can; return CT_Dependent; @@ -3018,14 +3048,13 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, // shortcut, use one AddInteger call instead of four for the next four // fields. assert(!(unsigned(epi.Variadic) & ~1) && - !(unsigned(epi.TypeQuals) & ~255) && !(unsigned(epi.RefQualifier) & ~3) && !(unsigned(epi.ExceptionSpec.Type) & ~15) && "Values larger than expected."); ID.AddInteger(unsigned(epi.Variadic) + - (epi.TypeQuals << 1) + - (epi.RefQualifier << 9) + - (epi.ExceptionSpec.Type << 11)); + (epi.RefQualifier << 1) + + (epi.ExceptionSpec.Type << 3)); + ID.Add(epi.TypeQuals); if (epi.ExceptionSpec.Type == EST_Dynamic) { for (QualType Ex : epi.ExceptionSpec.Exceptions) ID.AddPointer(Ex.getAsOpaquePtr()); @@ -3045,8 +3074,8 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { - Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(), - Ctx, isCanonicalUnqualified()); + Profile(ID, getReturnType(), param_type_begin(), getNumParams(), + getExtProtoInfo(), Ctx, isCanonicalUnqualified()); } QualType TypedefType::desugar() const { @@ -3143,14 +3172,23 @@ bool TagType::isBeingDefined() const { } bool RecordType::hasConstFields() const { - for (FieldDecl *FD : getDecl()->fields()) { - QualType FieldTy = FD->getType(); - if (FieldTy.isConstQualified()) - return true; - FieldTy = FieldTy.getCanonicalType(); - if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) - if (FieldRecTy->hasConstFields()) + std::vector<const RecordType*> RecordTypeList; + RecordTypeList.push_back(this); + unsigned NextToCheckIndex = 0; + + while (RecordTypeList.size() > NextToCheckIndex) { + for (FieldDecl *FD : + RecordTypeList[NextToCheckIndex]->getDecl()->fields()) { + QualType FieldTy = FD->getType(); + if (FieldTy.isConstQualified()) return true; + FieldTy = FieldTy.getCanonicalType(); + if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) { + if (llvm::find(RecordTypeList, FieldRecTy) == RecordTypeList.end()) + RecordTypeList.push_back(FieldRecTy); + } + } + ++NextToCheckIndex; } return false; } @@ -3202,6 +3240,7 @@ bool AttributedType::isCallingConv() const { case attr::RegCall: case attr::SwiftCall: case attr::VectorCall: + case attr::AArch64VectorPcs: case attr::Pascal: case attr::MSABI: case attr::SysVABI: @@ -3736,6 +3775,9 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index b6dc679bbf..b7b2f188d7 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -384,6 +384,9 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index fe05127c7f..031b44f11e 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -801,10 +801,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, printFunctionAfter(Info, OS); - if (unsigned quals = T->getTypeQuals()) { - OS << ' '; - AppendTypeQualList(OS, quals, Policy.Restrict); - } + if (!T->getTypeQuals().empty()) + OS << " " << T->getTypeQuals().getAsString(); switch (T->getRefQualifier()) { case RQ_None: @@ -861,6 +859,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, case CC_AAPCS_VFP: OS << " __attribute__((pcs(\"aapcs-vfp\")))"; break; + case CC_AArch64VectorCall: + OS << "__attribute__((aarch64_vector_pcs))"; + break; case CC_IntelOclBicc: OS << " __attribute__((intel_ocl_bicc))"; break; @@ -1154,9 +1155,13 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( D->getLocation()); if (PLoc.isValid()) { - OS << " at " << PLoc.getFilename() - << ':' << PLoc.getLine() - << ':' << PLoc.getColumn(); + OS << " at "; + StringRef File = PLoc.getFilename(); + if (Policy.RemapFilePaths) + OS << Policy.remapPath(File); + else + OS << File; + OS << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); } } @@ -1492,7 +1497,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, OS << ')'; break; } - + case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break; case attr::IntelOclBicc: OS << "inteloclbicc"; break; case attr::PreserveMost: OS << "preserve_most"; @@ -1501,6 +1506,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::PreserveAll: OS << "preserve_all"; break; + case attr::NoDeref: + OS << "noderef"; + break; } OS << "))"; } diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index 46844daf3b..846a608574 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -2205,13 +2205,12 @@ VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices, else this->VTableIndices = OwningArrayRef<size_t>(VTableIndices); - llvm::sort(this->VTableThunks.begin(), this->VTableThunks.end(), - [](const VTableLayout::VTableThunkTy &LHS, - const VTableLayout::VTableThunkTy &RHS) { - assert((LHS.first != RHS.first || LHS.second == RHS.second) && - "Different thunks should have unique indices!"); - return LHS.first < RHS.first; - }); + llvm::sort(this->VTableThunks, [](const VTableLayout::VTableThunkTy &LHS, + const VTableLayout::VTableThunkTy &RHS) { + assert((LHS.first != RHS.first || LHS.second == RHS.second) && + "Different thunks should have unique indices!"); + return LHS.first < RHS.first; + }); } VTableLayout::~VTableLayout() { } @@ -3407,10 +3406,9 @@ static void removeRedundantPaths(std::list<FullPathTy> &FullPaths) { 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; - })) { + if (llvm::all_of(SpecificPath, [&](const BaseSubobject &BSO) { + return OtherPath.count(BSO) != 0; + })) { return true; } } @@ -3486,10 +3484,9 @@ static const FullPathTy *selectBestPath(ASTContext &Context, // 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; - })) + if (llvm::none_of(SpecificPath, [&](const BaseSubobject &BSO) { + return BSO.getBase() == OverridingParent; + })) continue; CurrentOverrides.insert(OverridingMethod); } |