diff options
Diffstat (limited to 'lib/AST')
53 files changed, 13327 insertions, 7838 deletions
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index c45b52a65a4d..c05b160b8e3d 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -416,18 +416,26 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ << GetApproxValue(getComplexFloatImag()) << "i"; return; case APValue::LValue: { - LValueBase Base = getLValueBase(); - if (!Base) { - Out << "0"; - return; - } - bool IsReference = Ty->isReferenceType(); QualType InnerTy = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); if (InnerTy.isNull()) InnerTy = Ty; + LValueBase Base = getLValueBase(); + if (!Base) { + if (isNullPointer()) { + Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); + } else if (IsReference) { + Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" + << getLValueOffset().getQuantity(); + } else { + Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" + << getLValueOffset().getQuantity(); + } + return; + } + if (!hasLValuePath()) { // No lvalue path: just print the offset. CharUnits O = getLValueOffset(); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d50f4493788a..21b6f36e9aa7 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -48,6 +48,7 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/CommentOptions.h" #include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/FixedPoint.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" @@ -192,7 +193,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { isa<ObjCPropertyDecl>(D) || isa<RedeclarableTemplateDecl>(D) || isa<ClassTemplateSpecializationDecl>(D)) - DeclLoc = D->getLocStart(); + DeclLoc = D->getBeginLoc(); else { DeclLoc = D->getLocation(); if (DeclLoc.isMacroID()) { @@ -200,7 +201,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // If location of the typedef name is in a macro, it is because being // declared via a macro. Try using declaration's starting location as // the "declaration location". - DeclLoc = D->getLocStart(); + DeclLoc = D->getBeginLoc(); } else if (const auto *TD = dyn_cast<TagDecl>(D)) { // If location of the tag decl is inside a macro, but the spelling of // the tag name comes from a macro argument, it looks like a special @@ -795,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(); @@ -837,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); } - 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 *>(); + +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 *>(); + } } } + + 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) { @@ -885,7 +943,9 @@ void ASTContext::PrintStats() const { #define TYPE(Name, Parent) \ if (counts[Idx]) \ llvm::errs() << " " << counts[Idx] << " " << #Name \ - << " types\n"; \ + << " types, " << sizeof(Name##Type) << " each " \ + << "(" << counts[Idx] * sizeof(Name##Type) \ + << " bytes)\n"; \ TotalBytes += counts[Idx] * sizeof(Name##Type); \ ++Idx; #define ABSTRACT_TYPE(Name, Parent) @@ -929,14 +989,11 @@ void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M, if (auto *Listener = getASTMutationListener()) Listener->RedefinedHiddenDefinition(ND, M); - if (getLangOpts().ModulesLocalVisibility) - MergedDefModules[ND].push_back(M); - else - ND->setVisibleDespiteOwningModule(); + MergedDefModules[cast<NamedDecl>(ND->getCanonicalDecl())].push_back(M); } void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) { - auto It = MergedDefModules.find(ND); + auto It = MergedDefModules.find(cast<NamedDecl>(ND->getCanonicalDecl())); if (It == MergedDefModules.end()) return; @@ -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( @@ -2500,21 +2563,24 @@ const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( /// Get the copy initialization expression of VarDecl, or nullptr if /// none exists. -Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { +ASTContext::BlockVarCopyInit +ASTContext::getBlockVarCopyInit(const VarDecl*VD) const { assert(VD && "Passed null params"); assert(VD->hasAttr<BlocksAttr>() && "getBlockVarCopyInits - not __block var"); - llvm::DenseMap<const VarDecl*, Expr*>::iterator - I = BlockVarCopyInits.find(VD); - return (I != BlockVarCopyInits.end()) ? I->second : nullptr; + auto I = BlockVarCopyInits.find(VD); + if (I != BlockVarCopyInits.end()) + return I->second; + return {nullptr, false}; } /// Set the copy inialization expression of a block var decl. -void ASTContext::setBlockVarCopyInits(VarDecl*VD, Expr* Init) { - assert(VD && Init && "Passed null params"); +void ASTContext::setBlockVarCopyInit(const VarDecl*VD, Expr *CopyExpr, + bool CanThrow) { + assert(VD && CopyExpr && "Passed null params"); assert(VD->hasAttr<BlocksAttr>() && "setBlockVarCopyInits - not __block var"); - BlockVarCopyInits[VD] = Init; + BlockVarCopyInits[VD].setExprAndFlag(CopyExpr, CanThrow); } TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T, @@ -3695,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); - } + // 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); + auto *FTP = (FunctionProtoType *)Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); @@ -3870,7 +3926,7 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const { return QualType(newType, 0); } -QualType ASTContext::getAttributedType(AttributedType::Kind attrKind, +QualType ASTContext::getAttributedType(attr::Kind attrKind, QualType modifiedType, QualType equivalentType) { llvm::FoldingSetNodeID id; @@ -4130,8 +4186,10 @@ QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, (void)CheckT; } - T = new (*this, TypeAlignment) - ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl); + void *Mem = Allocate(ElaboratedType::totalSizeToAlloc<TagDecl *>(!!OwnedTagDecl), + TypeAlignment); + T = new (Mem) ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl); + Types.push_back(T); ElaboratedTypes.InsertNode(T, InsertPos); return QualType(T, 0); @@ -4262,7 +4320,7 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) { Arg = TemplateArgument(ArgType); } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { Expr *E = new (*this) DeclRefExpr( - NTTP, /*enclosing*/false, + *this, NTTP, /*enclosing*/ false, NTTP->getType().getNonLValueExprType(*this), Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); @@ -4542,8 +4600,8 @@ ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl, if (!protocols.empty()) { // Apply the protocol qualifers. bool hasError; - Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError, - true/*allowOnPointerType*/); + Canonical = getCanonicalType(applyObjCProtocolQualifiers( + Canonical, protocols, hasError, true /*allowOnPointerType*/)); assert(!hasError && "Error when apply protocol qualifier to bound type"); } } @@ -5098,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) { @@ -5762,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(); + if (CFConstantStringTypeDecl) + return CFConstantStringTypeDecl; - QualType FieldTypes[4]; - const char *FieldNames[4]; + assert(!CFConstantStringTagDecl && + "tag and typedef should be initialized together"); + CFConstantStringTagDecl = buildImplicitRecord("__NSConstantString_tag"); + CFConstantStringTagDecl->startDefinition(); - // 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"; + struct { + QualType Type; + const char *Name; + } Fields[5]; + unsigned Count = 0; - // 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); - } + /// 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; - 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"); + 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; } @@ -5959,7 +6053,7 @@ LangAS ASTContext::getOpenCLTypeAddrSpace(const Type *T) const { bool ASTContext::BlockRequiresCopying(QualType Ty, const VarDecl *D) { if (const CXXRecordDecl *record = Ty->getAsCXXRecordDecl()) { - const Expr *copyExpr = getBlockVarCopyInits(D); + const Expr *copyExpr = getBlockVarCopyInit(D).getCopyExpr(); if (!copyExpr && record->hasTrivialDestructor()) return false; return true; @@ -5999,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; @@ -6471,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: @@ -7677,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 @@ -8033,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. @@ -9384,9 +9481,11 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, // qualified with an address space. char *End; unsigned AddrSpace = strtoul(Str, &End, 10); - if (End != Str && AddrSpace != 0) { - Type = Context.getAddrSpaceQualType(Type, - getLangASFromTargetAS(AddrSpace)); + if (End != Str) { + // Note AddrSpace == 0 is not the same as an unspecified address space. + Type = Context.getAddrSpaceQualType( + Type, + Context.getLangASForBuiltinAddressSpace(AddrSpace)); Str = End; } if (c == '*') @@ -9717,6 +9816,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { cast<FunctionDecl>(D)->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; + // Implicit member function definitions, such as operator= might not be + // marked as template specializations, since they're not coming from a + // template but synthesized directly on the class. + IsExpInstDef |= + isa<CXXMethodDecl>(D) && + cast<CXXMethodDecl>(D)->getParent()->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition; + if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef) return false; } @@ -9766,6 +9873,12 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { const auto *VD = cast<VarDecl>(D); assert(VD->isFileVarDecl() && "Expected file scoped var"); + // If the decl is marked as `declare target to`, it should be emitted for the + // host and for the device. + if (LangOpts.OpenMP && + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + return true; + if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly && !isMSStaticDataMemberInlineDefinition(VD)) return false; @@ -9797,27 +9910,18 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (DeclMustBeEmitted(BindingVD)) return true; - // If the decl is marked as `declare target`, it should be emitted. - for (const auto *Decl : D->redecls()) { - if (!Decl->hasAttrs()) - continue; - if (const auto *Attr = Decl->getAttr<OMPDeclareTargetDeclAttr>()) - if (Attr->getMapType() != OMPDeclareTargetDeclAttr::MT_Link) - return true; - } - return false; } void ASTContext::forEachMultiversionedFunctionVersion( const FunctionDecl *FD, - llvm::function_ref<void(const FunctionDecl *)> Pred) const { + 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); @@ -10054,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 <> @@ -10082,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 @@ -10322,6 +10376,16 @@ QualType ASTContext::getCorrespondingSaturatedType(QualType Ty) const { } } +LangAS ASTContext::getLangASForBuiltinAddressSpace(unsigned AS) const { + if (LangOpts.OpenCL) + return getTargetInfo().getOpenCLBuiltinAddressSpace(AS); + + if (LangOpts.CUDA) + return getTargetInfo().getCUDABuiltinAddressSpace(AS); + + return getLangASFromTargetAS(AS); +} + // Explicitly instantiate this in case a Redeclarable<T> is used from a TU that // doesn't include ASTContext.h template @@ -10419,3 +10483,22 @@ unsigned char ASTContext::getFixedPointIBits(QualType Ty) const { return 0; } } + +FixedPointSemantics ASTContext::getFixedPointSemantics(QualType Ty) const { + assert(Ty->isFixedPointType()); + bool isSigned = Ty->isSignedFixedPointType(); + return FixedPointSemantics( + static_cast<unsigned>(getTypeSize(Ty)), getFixedPointScale(Ty), isSigned, + Ty->isSaturatedFixedPointType(), + !isSigned && getTargetInfo().doUnsignedFixedPointTypesHavePadding()); +} + +APFixedPoint ASTContext::getFixedPointMax(QualType Ty) const { + assert(Ty->isFixedPointType()); + return APFixedPoint::getMax(getFixedPointSemantics(Ty)); +} + +APFixedPoint ASTContext::getFixedPointMin(QualType Ty) const { + assert(Ty->isFixedPointType()); + return APFixedPoint::getMin(getFixedPointSemantics(Ty)); +} diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 50d2d2999e51..dd0585558572 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -334,6 +334,20 @@ void clang::FormatASTNodeDiagnosticArgument( switch (Kind) { default: llvm_unreachable("unknown ArgumentKind"); + case DiagnosticsEngine::ak_qual: { + assert(Modifier.empty() && Argument.empty() && + "Invalid modifier for Qualfiers argument"); + + Qualifiers Q(Qualifiers::fromOpaqueValue(Val)); + auto S = Q.getAsString(); + if (S.empty()) { + OS << "unqualified"; + NeedQuotes = false; + } else { + OS << Q.getAsString(); + } + break; + } case DiagnosticsEngine::ak_qualtype_pair: { TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val); QualType FromType = diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 8a653ecebae3..b52ec21943e6 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -13,7 +13,9 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDumperUtils.h" #include "clang/AST/Attr.h" +#include "clang/AST/AttrVisitor.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclLookups.h" @@ -22,6 +24,8 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/LocInfoType.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/TemplateArgumentVisitor.h" +#include "clang/AST/TextNodeDumper.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/Module.h" @@ -35,177 +39,35 @@ 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; - }; - - // 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 }; + class ASTDumper + : public ConstDeclVisitor<ASTDumper>, + public ConstStmtVisitor<ASTDumper>, + public ConstCommentVisitor<ASTDumper, void, const FullComment *>, + public TypeVisitor<ASTDumper>, + public ConstAttrVisitor<ASTDumper>, + public ConstTemplateArgumentVisitor<ASTDumper> { - // Indents ( `, -. | ) - static const TerminalColor IndentColor = { raw_ostream::BLUE, false }; + 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; + template<typename Fn> void dumpChild(Fn DoDumpChild) { + NodeDumper.AddChild(DoDumpChild); + } + template <typename Fn> void dumpChild(StringRef Label, Fn DoDumpChild) { + NodeDumper.AddChild(Label, 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, @@ -219,40 +81,39 @@ 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) {} + : 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); + void dumpStmt(const Stmt *S, StringRef Label = {}); // 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 dumpTypeAsChild(QualType T); void dumpTypeAsChild(const Type *T); - void dumpBareDeclRef(const Decl *Node); - void dumpDeclRef(const Decl *Node, const char *Label = nullptr); - void dumpName(const NamedDecl *D); - bool hasNodes(const DeclContext *DC); void dumpDeclContext(const DeclContext *DC); void dumpLookups(const DeclContext *DC, 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); @@ -261,6 +122,9 @@ namespace { void VisitComplexType(const ComplexType *T) { dumpTypeAsChild(T->getElementType()); } + void VisitLocInfoType(const LocInfoType *T) { + dumpTypeAsChild(T->getTypeSourceInfo()->getType()); + } void VisitPointerType(const PointerType *T) { dumpTypeAsChild(T->getPointeeType()); } @@ -270,92 +134,39 @@ namespace { void VisitReferenceType(const ReferenceType *T) { dumpTypeAsChild(T->getPointeeType()); } - void VisitRValueReferenceType(const ReferenceType *T) { - if (T->isSpelledAsLValue()) - OS << " written as lvalue reference"; - VisitReferenceType(T); - } void VisitMemberPointerType(const MemberPointerType *T) { dumpTypeAsChild(T->getClass()); dumpTypeAsChild(T->getPointeeType()); } void VisitArrayType(const ArrayType *T) { - switch (T->getSizeModifier()) { - case ArrayType::Normal: break; - case ArrayType::Static: OS << " static"; break; - case ArrayType::Star: OS << " *"; break; - } - OS << " " << T->getIndexTypeQualifiers().getAsString(); dumpTypeAsChild(T->getElementType()); } - void VisitConstantArrayType(const ConstantArrayType *T) { - OS << " " << T->getSize(); - VisitArrayType(T); - } void VisitVariableArrayType(const VariableArrayType *T) { - OS << " "; - dumpSourceRange(T->getBracketsRange()); VisitArrayType(T); dumpStmt(T->getSizeExpr()); } void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { - VisitArrayType(T); - OS << " "; - dumpSourceRange(T->getBracketsRange()); + dumpTypeAsChild(T->getElementType()); dumpStmt(T->getSizeExpr()); } void VisitDependentSizedExtVectorType( const DependentSizedExtVectorType *T) { - OS << " "; - dumpLocation(T->getAttributeLoc()); dumpTypeAsChild(T->getElementType()); dumpStmt(T->getSizeExpr()); } void VisitVectorType(const VectorType *T) { - switch (T->getVectorKind()) { - case VectorType::GenericVector: break; - case VectorType::AltiVecVector: OS << " altivec"; break; - case VectorType::AltiVecPixel: OS << " altivec pixel"; break; - case VectorType::AltiVecBool: OS << " altivec bool"; break; - case VectorType::NeonVector: OS << " neon"; break; - case VectorType::NeonPolyVector: OS << " neon poly"; break; - } - OS << " " << T->getNumElements(); dumpTypeAsChild(T->getElementType()); } void VisitFunctionType(const FunctionType *T) { - auto EI = T->getExtInfo(); - if (EI.getNoReturn()) OS << " noreturn"; - if (EI.getProducesResult()) OS << " produces_result"; - if (EI.getHasRegParm()) OS << " regparm " << EI.getRegParm(); - OS << " " << FunctionType::getNameForCallConv(EI.getCC()); dumpTypeAsChild(T->getReturnType()); } void VisitFunctionProtoType(const FunctionProtoType *T) { - auto EPI = T->getExtProtoInfo(); - if (EPI.HasTrailingReturn) OS << " trailing_return"; - if (T->isConst()) OS << " const"; - if (T->isVolatile()) OS << " volatile"; - if (T->isRestrict()) OS << " restrict"; - switch (EPI.RefQualifier) { - case RQ_None: break; - case RQ_LValue: OS << " &"; break; - case RQ_RValue: OS << " &&"; break; - } - // FIXME: Exception specification. - // FIXME: Consumed parameters. VisitFunctionType(T); for (QualType PT : T->getParamTypes()) dumpTypeAsChild(PT); - if (EPI.Variadic) + if (T->getExtProtoInfo().Variadic) dumpChild([=] { OS << "..."; }); } - void VisitUnresolvedUsingType(const UnresolvedUsingType *T) { - dumpDeclRef(T->getDecl()); - } - void VisitTypedefType(const TypedefType *T) { - dumpDeclRef(T->getDecl()); - } void VisitTypeOfExprType(const TypeOfExprType *T) { dumpStmt(T->getUnderlyingExpr()); } @@ -363,25 +174,12 @@ namespace { dumpStmt(T->getUnderlyingExpr()); } void VisitUnaryTransformType(const UnaryTransformType *T) { - switch (T->getUTTKind()) { - case UnaryTransformType::EnumUnderlyingType: - OS << " underlying_type"; - break; - } dumpTypeAsChild(T->getBaseType()); } - void VisitTagType(const TagType *T) { - dumpDeclRef(T->getDecl()); - } void VisitAttributedType(const AttributedType *T) { // FIXME: AttrKind dumpTypeAsChild(T->getModifiedType()); } - void VisitTemplateTypeParmType(const TemplateTypeParmType *T) { - OS << " depth " << T->getDepth() << " index " << T->getIndex(); - if (T->isParameterPack()) OS << " pack"; - dumpDeclRef(T->getDecl()); - } void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { dumpTypeAsChild(T->getReplacedParameter()); } @@ -390,25 +188,12 @@ namespace { dumpTypeAsChild(T->getReplacedParameter()); dumpTemplateArgument(T->getArgumentPack()); } - void VisitAutoType(const AutoType *T) { - if (T->isDecltypeAuto()) OS << " decltype(auto)"; - if (!T->isDeduced()) - OS << " undeduced"; - } void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { - if (T->isTypeAlias()) OS << " alias"; - OS << " "; T->getTemplateName().dump(OS); for (auto &Arg : *T) dumpTemplateArgument(Arg); if (T->isTypeAlias()) dumpTypeAsChild(T->getAliasedType()); } - void VisitInjectedClassNameType(const InjectedClassNameType *T) { - dumpDeclRef(T->getDecl()); - } - void VisitObjCInterfaceType(const ObjCInterfaceType *T) { - dumpDeclRef(T->getDecl()); - } void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { dumpTypeAsChild(T->getPointeeType()); } @@ -422,7 +207,6 @@ namespace { dumpTypeAsChild(T->getOriginalType()); } void VisitPackExpansionType(const PackExpansionType *T) { - if (auto N = T->getNumExpansions()) OS << " expansions " << *N; if (!T->isSugared()) dumpTypeAsChild(T->getPattern()); } @@ -450,6 +234,7 @@ namespace { // OpenMP decls void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D); void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D); + void VisitOMPRequiresDecl(const OMPRequiresDecl *D); void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D); // C++ Decls @@ -460,12 +245,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( @@ -504,96 +283,47 @@ namespace { void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D); void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); + void Visit(const BlockDecl::Capture &C); void VisitBlockDecl(const BlockDecl *D); // Stmts. - void VisitStmt(const Stmt *Node); void VisitDeclStmt(const DeclStmt *Node); void VisitAttributedStmt(const AttributedStmt *Node); - void VisitLabelStmt(const LabelStmt *Node); - void VisitGotoStmt(const GotoStmt *Node); void VisitCXXCatchStmt(const CXXCatchStmt *Node); void VisitCapturedStmt(const CapturedStmt *Node); // OpenMP + void Visit(const OMPClause *C); void VisitOMPExecutableDirective(const OMPExecutableDirective *Node); // Exprs - void VisitExpr(const Expr *Node); - void VisitCastExpr(const CastExpr *Node); - void VisitImplicitCastExpr(const ImplicitCastExpr *Node); - void VisitDeclRefExpr(const DeclRefExpr *Node); - void VisitPredefinedExpr(const PredefinedExpr *Node); - void VisitCharacterLiteral(const CharacterLiteral *Node); - void VisitIntegerLiteral(const IntegerLiteral *Node); - void VisitFixedPointLiteral(const FixedPointLiteral *Node); - 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); - void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node); - void VisitBinaryOperator(const BinaryOperator *Node); - void VisitCompoundAssignOperator(const CompoundAssignOperator *Node); - void VisitAddrLabelExpr(const AddrLabelExpr *Node); void VisitBlockExpr(const BlockExpr *Node); void VisitOpaqueValueExpr(const OpaqueValueExpr *Node); void VisitGenericSelectionExpr(const GenericSelectionExpr *E); // C++ - void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node); - void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node); - void VisitCXXThisExpr(const CXXThisExpr *Node); - void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node); - void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node); - void VisitCXXConstructExpr(const CXXConstructExpr *Node); - void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); - void VisitCXXNewExpr(const CXXNewExpr *Node); - void VisitCXXDeleteExpr(const CXXDeleteExpr *Node); - void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node); - void VisitExprWithCleanups(const ExprWithCleanups *Node); - void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node); - void dumpCXXTemporary(const CXXTemporary *Temporary); void VisitLambdaExpr(const LambdaExpr *Node) { - VisitExpr(Node); dumpDecl(Node->getLambdaClass()); } void VisitSizeOfPackExpr(const SizeOfPackExpr *Node); - void - VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node); // ObjC void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); - void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node); - void VisitObjCMessageExpr(const ObjCMessageExpr *Node); - void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node); - void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node); - void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node); - void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node); - void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node); - void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node); - void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node); // Comments. - const char *getCommandName(unsigned CommandID); - void dumpComment(const Comment *C); + void dumpComment(const Comment *C, const FullComment *FC); - // Inline comments. - void visitTextComment(const TextComment *C); - void visitInlineCommandComment(const InlineCommandComment *C); - void visitHTMLStartTagComment(const HTMLStartTagComment *C); - void visitHTMLEndTagComment(const HTMLEndTagComment *C); + void VisitExpressionTemplateArgument(const TemplateArgument &TA) { + dumpStmt(TA.getAsExpr()); + } + void VisitPackTemplateArgument(const TemplateArgument &TA) { + for (const auto &TArg : TA.pack_elements()) + dumpTemplateArgument(TArg); + } - // 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); +// Implements Visit methods for Attrs. +#include "clang/AST/AttrNodeTraverse.inc" }; } @@ -601,188 +331,31 @@ 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()) return dumpTypeAsChild(SQT.Ty); dumpChild([=] { - OS << "QualType"; - dumpPointer(T.getAsOpaquePtr()); - OS << " "; - dumpBareType(T, false); - OS << " " << T.split().Quals.getAsString(); + NodeDumper.Visit(T); dumpTypeAsChild(T.split().Ty); }); } void ASTDumper::dumpTypeAsChild(const Type *T) { dumpChild([=] { - if (!T) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>>"; + NodeDumper.Visit(T); + if (!T) return; - } - if (const LocInfoType *LIT = llvm::dyn_cast<LocInfoType>(T)) { - { - ColorScope Color(*this, TypeColor); - OS << "LocInfo Type"; - } - dumpPointer(T); - dumpTypeAsChild(LIT->getTypeSourceInfo()->getType()); - return; - } - - { - ColorScope Color(*this, TypeColor); - OS << T->getTypeClassName() << "Type"; - } - dumpPointer(T); - OS << " "; - dumpBareType(QualType(T, 0), false); + TypeVisitor<ASTDumper>::Visit(T); QualType SingleStepDesugar = T->getLocallyUnqualifiedSingleStepDesugaredType(); if (SingleStepDesugar != QualType(T, 0)) - OS << " sugar"; - if (T->isDependentType()) - OS << " dependent"; - else if (T->isInstantiationDependentType()) - OS << " instantiation_dependent"; - if (T->isVariablyModifiedType()) - OS << " variably_modified"; - if (T->containsUnexpandedParameterPack()) - OS << " contains_unexpanded_pack"; - if (T->isFromAST()) - OS << " imported"; - - TypeVisitor<ASTDumper>::Visit(T); - - if (SingleStepDesugar != QualType(T, 0)) dumpTypeAsChild(SingleStepDesugar); }); } -void ASTDumper::dumpBareDeclRef(const Decl *D) { - 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; - - dumpChild([=]{ - if (Label) - OS << Label << ' '; - dumpBareDeclRef(D); - }); -} - -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; @@ -791,8 +364,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>"; }); } @@ -801,12 +374,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(); @@ -821,14 +394,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"; @@ -850,7 +423,7 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { if (HasUndeserializedLookups) { dumpChild([=] { - ColorScope Color(*this, UndeserializedColor); + ColorScope Color(OS, ShowColors, UndeserializedColor); OS << "<undeserialized lookups>"; }); } @@ -859,87 +432,18 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { void ASTDumper::dumpAttr(const Attr *A) { dumpChild([=] { - { - ColorScope Color(*this, AttrColor); - - switch (A->getKind()) { -#define ATTR(X) case attr::X: OS << #X; break; -#include "clang/Basic/AttrList.inc" - } - OS << "Attr"; - } - dumpPointer(A); - dumpSourceRange(A->getRange()); - if (A->isInherited()) - OS << " Inherited"; - if (A->isImplicit()) - OS << " Implicit"; -#include "clang/AST/AttrDump.inc" + NodeDumper.Visit(A); + ConstAttrVisitor<ASTDumper>::Visit(A); }); } -static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {} - -template<typename T> -static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) { - const T *First = D->getFirstDecl(); - if (First != D) - OS << " first " << First; -} - -template<typename T> -static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) { - const T *Prev = D->getPreviousDecl(); - if (Prev) - OS << " prev " << Prev; -} - -/// Dump the previous declaration in the redeclaration chain for a declaration, -/// if any. -static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) { - switch (D->getKind()) { -#define DECL(DERIVED, BASE) \ - case Decl::DERIVED: \ - return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D)); -#define ABSTRACT_DECL(DECL) -#include "clang/AST/DeclNodes.inc" - } - llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); -} - //===----------------------------------------------------------------------===// // 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()); - } else if (Init->isBaseInitializer()) { - dumpType(QualType(Init->getBaseClass(), 0)); - } else if (Init->isDelegatingInitializer()) { - dumpType(Init->getTypeSourceInfo()->getType()); - } else { - llvm_unreachable("Unknown initializer type"); - } + NodeDumper.Visit(Init); dumpStmt(Init->getInit()); }); } @@ -959,8 +463,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) { @@ -968,49 +473,11 @@ 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); - - switch (A.getKind()) { - case TemplateArgument::Null: - OS << " null"; - break; - case TemplateArgument::Type: - OS << " type"; - dumpType(A.getAsType()); - break; - case TemplateArgument::Declaration: - OS << " decl"; - dumpDeclRef(A.getAsDecl()); - break; - case TemplateArgument::NullPtr: - OS << " nullptr"; - break; - case TemplateArgument::Integral: - OS << " integral " << A.getAsIntegral(); - break; - case TemplateArgument::Template: - OS << " template "; - A.getAsTemplate().dump(OS); - break; - case TemplateArgument::TemplateExpansion: - OS << " template expansion"; - A.getAsTemplateOrTemplatePattern().dump(OS); - break; - case TemplateArgument::Expression: - OS << " expr"; - dumpStmt(A.getAsExpr()); - break; - case TemplateArgument::Pack: - OS << " pack"; - for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); - I != E; ++I) - dumpTemplateArgument(*I); - break; - } + NodeDumper.Visit(A, R, From, Label); + ConstTemplateArgumentVisitor<ASTDumper>::Visit(A); }); } @@ -1032,46 +499,9 @@ void ASTDumper::dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) { void ASTDumper::dumpDecl(const Decl *D) { dumpChild([=] { - if (!D) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>>"; + NodeDumper.Visit(D); + if (!D) return; - } - - { - ColorScope Color(*this, DeclKindNameColor); - OS << D->getDeclKindName() << "Decl"; - } - dumpPointer(D); - if (D->getLexicalDeclContext() != D->getDeclContext()) - OS << " parent " << cast<Decl>(D->getDeclContext()); - dumpPreviousDecl(OS, D); - dumpSourceRange(D->getSourceRange()); - OS << ' '; - dumpLocation(D->getLocation()); - if (D->isFromASTFile()) - OS << " imported"; - if (Module *M = D->getOwningModule()) - OS << " in " << M->getFullModuleName(); - if (auto *ND = dyn_cast<NamedDecl>(D)) - for (Module *M : D->getASTContext().getModulesWithMergedDefinition( - const_cast<NamedDecl *>(ND))) - dumpChild([=] { OS << "also in " << M->getFullModuleName(); }); - if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) - if (ND->isHidden()) - OS << " hidden"; - if (D->isImplicit()) - OS << " implicit"; - if (D->isUsed()) - OS << " used"; - else if (D->isThisDeclarationReferenced()) - OS << " referenced"; - if (D->isInvalidDecl()) - OS << " invalid"; - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - if (FD->isConstexpr()) - OS << " constexpr"; - ConstDeclVisitor<ASTDumper>::Visit(D); @@ -1081,22 +511,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()); @@ -1109,16 +542,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()) @@ -1126,23 +559,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); + NodeDumper.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) @@ -1166,7 +599,7 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { if (D->isTrivial()) OS << " trivial"; - if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) { + if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); switch (EPI.ExceptionSpec.Type) { default: break; @@ -1179,23 +612,7 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { } } - if (const FunctionTemplateSpecializationInfo *FTSI = - D->getTemplateSpecializationInfo()) - dumpTemplateArgumentList(*FTSI->TemplateArguments); - - if (!D->param_begin() && D->getNumParams()) - dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; }); - else - for (const ParmVarDecl *Parameter : D->parameters()) - dumpDecl(Parameter); - - if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D)) - for (CXXConstructorDecl::init_const_iterator I = C->init_begin(), - E = C->init_end(); - I != E; ++I) - dumpCXXCtorInitializer(*I); - - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { if (MD->size_overridden_methods() != 0) { auto dumpOverride = [=](const CXXMethodDecl *D) { SplitQualType T_split = D->getType().split(); @@ -1218,13 +635,26 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { } } + if (const auto *FTSI = D->getTemplateSpecializationInfo()) + dumpTemplateArgumentList(*FTSI->TemplateArguments); + + if (!D->param_begin() && D->getNumParams()) + dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; }); + else + for (const ParmVarDecl *Parameter : D->parameters()) + dumpDecl(Parameter); + + if (const auto *C = dyn_cast<CXXConstructorDecl>(D)) + for (const auto *I : C->inits()) + dumpCXXCtorInitializer(I); + if (D->doesThisDeclarationHaveABody()) dumpStmt(D->getBody()); } 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()) @@ -1237,8 +667,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); @@ -1272,8 +702,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); } @@ -1320,12 +750,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 = "; @@ -1336,13 +767,36 @@ void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { case OMPDeclareReductionDecl::CallInit: break; } + } + + 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(OS, ShowColors, NullColor); + OS << "<<<NULL>>> OMPClause"; + return; + } + { + ColorScope Color(OS, ShowColors, AttrColor); + StringRef ClauseName(getOpenMPClauseName(C->getClauseKind())); + OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper() + << ClauseName.drop_front() << "Clause"; + } + 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()); } @@ -1351,31 +805,31 @@ 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()) - dumpDeclRef(D->getOriginalNamespace(), "original"); + NodeDumper.dumpDeclRef(D->getOriginalNamespace(), "original"); } void ASTDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { OS << ' '; - dumpBareDeclRef(D->getNominatedNamespace()); + NodeDumper.dumpBareDeclRef(D->getNominatedNamespace()); } void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { - dumpName(D); - dumpDeclRef(D->getAliasedNamespace()); + NodeDumper.dumpName(D); + NodeDumper.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()); } @@ -1387,7 +841,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; @@ -1415,7 +869,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "DefaultConstructor"; } FLAG(hasDefaultConstructor, exists); @@ -1429,7 +883,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "CopyConstructor"; } FLAG(hasSimpleCopyConstructor, simple); @@ -1447,7 +901,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "MoveConstructor"; } FLAG(hasMoveConstructor, exists); @@ -1464,7 +918,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "CopyAssignment"; } FLAG(hasTrivialCopyAssignment, trivial); @@ -1478,7 +932,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "MoveAssignment"; } FLAG(hasMoveAssignment, exists); @@ -1492,7 +946,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { dumpChild([=] { { - ColorScope Color(*this, DeclKindNameColor); + ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << "Destructor"; } FLAG(hasSimpleDestructor, simple); @@ -1511,8 +965,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 << "..."; }); @@ -1524,10 +978,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 @@ -1551,7 +1005,7 @@ void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D, case TSK_Undeclared: case TSK_ImplicitInstantiation: if (DumpRefOnly) - dumpDeclRef(Redecl); + NodeDumper.dumpDeclRef(Redecl); else dumpDecl(Redecl); DumpedAny = true; @@ -1563,31 +1017,30 @@ void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D, // Ensure we dump at least one decl for each specialization. if (!DumpedAny) - dumpDeclRef(D); + NodeDumper.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( @@ -1610,11 +1063,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()); } @@ -1638,19 +1091,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()); + 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()); + dumpTemplateArgument(D->getDefaultArgument(), SourceRange(), + D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" + : "previous"); } void ASTDumper::VisitTemplateTemplateParmDecl( @@ -1658,10 +1117,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()); + dumpTemplateArgumentLoc( + D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); } void ASTDumper::VisitUsingDecl(const UsingDecl *D) { @@ -1684,12 +1145,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()); } @@ -1701,21 +1162,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()); }); } @@ -1728,12 +1189,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()); } @@ -1743,8 +1204,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"; @@ -1772,8 +1233,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); @@ -1790,7 +1251,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; @@ -1806,47 +1267,47 @@ 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); - dumpDeclRef(D->getClassInterface()); - dumpObjCTypeParamList(D->getTypeParamList()); - dumpDeclRef(D->getImplementation()); + NodeDumper.dumpName(D); + NodeDumper.dumpDeclRef(D->getClassInterface()); + NodeDumper.dumpDeclRef(D->getImplementation()); for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) - dumpDeclRef(*I); + NodeDumper.dumpDeclRef(*I); + dumpObjCTypeParamList(D->getTypeParamList()); } void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { - dumpName(D); - dumpDeclRef(D->getClassInterface()); - dumpDeclRef(D->getCategoryDecl()); + NodeDumper.dumpName(D); + NodeDumper.dumpDeclRef(D->getClassInterface()); + NodeDumper.dumpDeclRef(D->getCategoryDecl()); } void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { - dumpName(D); + NodeDumper.dumpName(D); for (auto *Child : D->protocols()) - dumpDeclRef(Child); + NodeDumper.dumpDeclRef(Child); } void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { - dumpName(D); - dumpObjCTypeParamList(D->getTypeParamListAsWritten()); - dumpDeclRef(D->getSuperClass(), "super"); + NodeDumper.dumpName(D); + NodeDumper.dumpDeclRef(D->getSuperClass(), "super"); - dumpDeclRef(D->getImplementation()); + NodeDumper.dumpDeclRef(D->getImplementation()); for (auto *Child : D->protocols()) - dumpDeclRef(Child); + NodeDumper.dumpDeclRef(Child); + dumpObjCTypeParamList(D->getTypeParamListAsWritten()); } void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { - dumpName(D); - dumpDeclRef(D->getSuperClass(), "super"); - dumpDeclRef(D->getClassInterface()); + NodeDumper.dumpName(D); + NodeDumper.dumpDeclRef(D->getSuperClass(), "super"); + NodeDumper.dumpDeclRef(D->getClassInterface()); for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(), E = D->init_end(); I != E; ++I) @@ -1854,13 +1315,13 @@ void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { } void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) { - dumpName(D); - dumpDeclRef(D->getClassInterface()); + NodeDumper.dumpName(D); + NodeDumper.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"; @@ -1892,20 +1353,28 @@ void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { if (Attrs & ObjCPropertyDecl::OBJC_PR_class) OS << " class"; if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) - dumpDeclRef(D->getGetterMethodDecl(), "getter"); + NodeDumper.dumpDeclRef(D->getGetterMethodDecl(), "getter"); if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) - dumpDeclRef(D->getSetterMethodDecl(), "setter"); + NodeDumper.dumpDeclRef(D->getSetterMethodDecl(), "setter"); } } void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { - dumpName(D->getPropertyDecl()); + NodeDumper.dumpName(D->getPropertyDecl()); if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) OS << " synthesize"; else OS << " dynamic"; - dumpDeclRef(D->getPropertyDecl()); - dumpDeclRef(D->getPropertyIvarDecl()); + NodeDumper.dumpDeclRef(D->getPropertyDecl()); + NodeDumper.dumpDeclRef(D->getPropertyIvarDecl()); +} + +void ASTDumper::Visit(const BlockDecl::Capture &C) { + dumpChild([=] { + NodeDumper.Visit(C); + if (C.hasCopyExpr()) + dumpStmt(C.getCopyExpr()); + }); } void ASTDumper::VisitBlockDecl(const BlockDecl *D) { @@ -1918,21 +1387,8 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) { if (D->capturesCXXThis()) dumpChild([=]{ OS << "capture this"; }); - for (const auto &I : D->captures()) { - dumpChild([=] { - OS << "capture"; - if (I.isByRef()) - OS << " byref"; - if (I.isNested()) - OS << " nested"; - if (I.getVariable()) { - OS << ' '; - dumpBareDeclRef(I.getVariable()); - } - if (I.hasCopyExpr()) - dumpStmt(I.getCopyExpr()); - }); - } + for (const auto &I : D->captures()) + Visit(I); dumpStmt(D->getBody()); } @@ -1940,42 +1396,27 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) { // Stmt dumping methods. //===----------------------------------------------------------------------===// -void ASTDumper::dumpStmt(const Stmt *S) { - dumpChild([=] { +void ASTDumper::dumpStmt(const Stmt *S, StringRef Label) { + dumpChild(Label, [=] { + NodeDumper.Visit(S); + if (!S) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>>"; return; } + ConstStmtVisitor<ASTDumper>::Visit(S); + // Some statements have custom mechanisms for dumping their children. - if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { - VisitDeclStmt(DS); - return; - } - if (const GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(S)) { - VisitGenericSelectionExpr(GSE); + if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S)) { return; } - ConstStmtVisitor<ASTDumper>::Visit(S); - 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) @@ -1983,31 +1424,17 @@ 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::VisitLabelStmt(const LabelStmt *Node) { - VisitStmt(Node); - OS << " '" << Node->getName() << "'"; -} - -void ASTDumper::VisitGotoStmt(const GotoStmt *Node) { - VisitStmt(Node); - OS << " '" << Node->getLabel()->getName() << "'"; - dumpPointer(Node->getLabel()); -} - void ASTDumper::VisitCXXCatchStmt(const CXXCatchStmt *Node) { - VisitStmt(Node); dumpDecl(Node->getExceptionDecl()); } void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) { - VisitStmt(Node); dumpDecl(Node->getCapturedDecl()); } @@ -2015,287 +1442,41 @@ void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) { // OpenMP dumping methods. //===----------------------------------------------------------------------===// +void ASTDumper::Visit(const OMPClause *C) { + dumpChild([=] { + NodeDumper.Visit(C); + for (auto *S : C->children()) + dumpStmt(S); + }); +} + void ASTDumper::VisitOMPExecutableDirective( const OMPExecutableDirective *Node) { - VisitStmt(Node); - for (auto *C : Node->clauses()) { - dumpChild([=] { - if (!C) { - ColorScope Color(*this, NullColor); - OS << "<<<NULL>>> OMPClause"; - return; - } - { - ColorScope Color(*this, AttrColor); - StringRef ClauseName(getOpenMPClauseName(C->getClauseKind())); - OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper() - << ClauseName.drop_front() << "Clause"; - } - dumpPointer(C); - dumpSourceRange(SourceRange(C->getLocStart(), C->getLocEnd())); - if (C->isImplicit()) - OS << " <implicit>"; - for (auto *S : C->children()) - dumpStmt(S); - }); - } + for (const auto *C : Node->clauses()) + Visit(C); } //===----------------------------------------------------------------------===// // 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; - - OS << " ("; - bool First = true; - for (CastExpr::path_const_iterator I = Node->path_begin(), - E = Node->path_end(); - I != E; ++I) { - const CXXBaseSpecifier *Base = *I; - if (!First) - OS << " -> "; - - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - - if (Base->isVirtual()) - OS << "virtual "; - OS << RD->getName(); - First = false; - } - - OS << ')'; -} - -void ASTDumper::VisitCastExpr(const CastExpr *Node) { - VisitExpr(Node); - OS << " <"; - { - ColorScope Color(*this, CastColor); - OS << Node->getCastKindName(); - } - dumpBasePath(OS, Node); - OS << ">"; -} - -void ASTDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) { - VisitCastExpr(Node); - if (Node->isPartOfExplicitCast()) - OS << " part_of_explicit_cast"; -} - -void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { - VisitExpr(Node); - - OS << " "; - dumpBareDeclRef(Node->getDecl()); - if (Node->getDecl() != Node->getFoundDecl()) { - OS << " ("; - dumpBareDeclRef(Node->getFoundDecl()); - OS << ")"; - } -} - -void ASTDumper::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node) { - VisitExpr(Node); - OS << " ("; - if (!Node->requiresADL()) - OS << "no "; - OS << "ADL) = '" << Node->getName() << '\''; - - UnresolvedLookupExpr::decls_iterator - I = Node->decls_begin(), E = Node->decls_end(); - if (I == E) - OS << " empty"; - for (; I != E; ++I) - dumpPointer(*I); -} - -void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { - VisitExpr(Node); - - { - ColorScope Color(*this, DeclKindNameColor); - OS << " " << Node->getDecl()->getDeclKindName() << "Decl"; - } - OS << "='" << *Node->getDecl() << "'"; - dumpPointer(Node->getDecl()); - if (Node->isFreeIvar()) - OS << " isFreeIvar"; -} - -void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { - VisitExpr(Node); - OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType()); -} - -void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { - VisitExpr(Node); - ColorScope Color(*this, ValueColor); - OS << " " << Node->getValue(); -} - -void ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) { - VisitExpr(Node); - - bool isSigned = Node->getType()->isSignedIntegerType(); - ColorScope Color(*this, ValueColor); - OS << " " << Node->getValue().toString(10, isSigned); -} - -void ASTDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) { - VisitExpr(Node); - - ColorScope Color(*this, ValueColor); - OS << " " << Node->getValueAsString(/*Radix=*/10); -} - -void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) { - VisitExpr(Node); - ColorScope Color(*this, ValueColor); - OS << " " << Node->getValueAsApproximateDouble(); -} - -void ASTDumper::VisitStringLiteral(const StringLiteral *Str) { - VisitExpr(Str); - ColorScope Color(*this, ValueColor); - OS << " "; - Str->outputString(OS); -} void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) { - VisitExpr(ILE); if (auto *Filler = ILE->getArrayFiller()) { - dumpChild([=] { - OS << "array filler"; - dumpStmt(Filler); - }); + dumpStmt(Filler, "array_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()) - OS << " cannot overflow"; -} - -void ASTDumper::VisitUnaryExprOrTypeTraitExpr( - const UnaryExprOrTypeTraitExpr *Node) { - VisitExpr(Node); - switch(Node->getKind()) { - case UETT_SizeOf: - OS << " sizeof"; - break; - case UETT_AlignOf: - OS << " alignof"; - break; - case UETT_VecStep: - OS << " vec_step"; - break; - case UETT_OpenMPRequiredSimdAlign: - OS << " __builtin_omp_required_simd_align"; - break; - } - if (Node->isArgumentType()) - dumpType(Node->getArgumentType()); -} - -void ASTDumper::VisitMemberExpr(const MemberExpr *Node) { - VisitExpr(Node); - OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl(); - 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()); - OS << " ComputeResultTy="; - 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()); @@ -2305,7 +1486,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"; } @@ -2320,394 +1501,42 @@ void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) { } } -// GNU extensions. - -void ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { - VisitExpr(Node); - OS << " " << Node->getLabel()->getName(); - dumpPointer(Node->getLabel()); -} - //===----------------------------------------------------------------------===// // C++ Expressions //===----------------------------------------------------------------------===// -void ASTDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) { - VisitExpr(Node); - OS << " " << Node->getCastName() - << "<" << Node->getTypeAsWritten().getAsString() << ">" - << " <" << Node->getCastKindName(); - dumpBasePath(OS, Node); - OS << ">"; -} - -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()); - if (Node->isListInitialization()) - OS << " list"; -} - -void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { - VisitExpr(Node); - CXXConstructorDecl *Ctor = Node->getConstructor(); - dumpType(Ctor->getType()); - if (Node->isElidable()) - OS << " elidable"; - if (Node->isListInitialization()) - OS << " list"; - if (Node->isStdInitListInitialization()) - OS << " std::initializer_list"; - if (Node->requiresZeroInitialization()) - OS << " zeroing"; -} - -void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) { - VisitExpr(Node); - OS << " "; - dumpCXXTemporary(Node->getTemporary()); -} - -void ASTDumper::VisitCXXNewExpr(const CXXNewExpr *Node) { - VisitExpr(Node); - if (Node->isGlobalNew()) - OS << " global"; - if (Node->isArray()) - OS << " array"; - if (Node->getOperatorNew()) { - OS << ' '; - dumpBareDeclRef(Node->getOperatorNew()); - } - // We could dump the deallocation function used in case of error, but it's - // usually not that interesting. -} - -void ASTDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) { - VisitExpr(Node); - if (Node->isGlobalDelete()) - OS << " global"; - if (Node->isArrayForm()) - OS << " array"; - if (Node->getOperatorDelete()) { - OS << ' '; - dumpBareDeclRef(Node->getOperatorDelete()); - } -} - -void -ASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) { - VisitExpr(Node); - if (const ValueDecl *VD = Node->getExtendingDecl()) { - OS << " extended by "; - 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()); if (Node->isPartiallySubstituted()) for (const auto &A : Node->getPartialArguments()) dumpTemplateArgument(A); } -void ASTDumper::VisitCXXDependentScopeMemberExpr( - const CXXDependentScopeMemberExpr *Node) { - VisitExpr(Node); - OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember(); -} - //===----------------------------------------------------------------------===// // Obj-C Expressions //===----------------------------------------------------------------------===// -void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { - VisitExpr(Node); - OS << " selector="; - Node->getSelector().print(OS); - switch (Node->getReceiverKind()) { - case ObjCMessageExpr::Instance: - break; - - case ObjCMessageExpr::Class: - OS << " class="; - dumpBareType(Node->getClassReceiver()); - break; - - case ObjCMessageExpr::SuperInstance: - OS << " super (instance)"; - break; - - case ObjCMessageExpr::SuperClass: - OS << " super (class)"; - break; - } -} - -void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { - VisitExpr(Node); - if (auto *BoxingMethod = Node->getBoxingMethod()) { - OS << " selector="; - BoxingMethod->getSelector().print(OS); - } -} - void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { - VisitStmt(Node); if (const VarDecl *CatchParam = Node->getCatchParamDecl()) dumpDecl(CatchParam); - else - OS << " catch all"; -} - -void ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) { - VisitExpr(Node); - 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()) - Node->getImplicitPropertyGetter()->getSelector().print(OS); - else - OS << "(null)"; - - OS << "\" Setter=\""; - if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) - Setter->getSelector().print(OS); - else - OS << "(null)"; - OS << "\""; - } else { - OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"'; - } - - if (Node->isSuperReceiver()) - OS << " super"; - - OS << " Messaging="; - if (Node->isMessagingGetter() && Node->isMessagingSetter()) - OS << "Getter&Setter"; - else if (Node->isMessagingGetter()) - OS << "Getter"; - else if (Node->isMessagingSetter()) - OS << "Setter"; -} - -void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { - VisitExpr(Node); - if (Node->isArraySubscriptRefExpr()) - OS << " Kind=ArraySubscript GetterForArray=\""; - else - OS << " Kind=DictionarySubscript GetterForDictionary=\""; - if (Node->getAtIndexMethodDecl()) - Node->getAtIndexMethodDecl()->getSelector().print(OS); - else - OS << "(null)"; - - if (Node->isArraySubscriptRefExpr()) - OS << "\" SetterForArray=\""; - else - OS << "\" SetterForDictionary=\""; - if (Node->setAtIndexMethodDecl()) - Node->setAtIndexMethodDecl()->getSelector().print(OS); - else - OS << "(null)"; -} - -void ASTDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) { - VisitExpr(Node); - OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); } //===----------------------------------------------------------------------===// // 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 //===----------------------------------------------------------------------===// @@ -2816,12 +1645,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 b360b3910636..44832557e97b 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTImporter.h" +#include "clang/AST/ASTImporterLookupTable.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTStructuralEquivalence.h" @@ -71,10 +72,43 @@ namespace clang { + 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."; + } + + void ImportError::log(raw_ostream &OS) const { + OS << toString(); + } + + 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); @@ -85,9 +119,13 @@ namespace clang { } SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) { - // Currently only FunctionDecl is supported - auto FD = cast<FunctionDecl>(D); - return getCanonicalForwardRedeclChain<FunctionDecl>(FD); + if (auto *FD = dyn_cast<FunctionDecl>(D)) + return getCanonicalForwardRedeclChain<FunctionDecl>(FD); + if (auto *VD = dyn_cast<VarDecl>(D)) + return getCanonicalForwardRedeclChain<VarDecl>(VD); + if (auto *TD = dyn_cast<TagDecl>(D)) + return getCanonicalForwardRedeclChain<TagDecl>(TD); + llvm_unreachable("Bad declaration kind"); } void updateFlags(const Decl *From, Decl *To) { @@ -97,12 +135,110 @@ namespace clang { To->setIsUsed(); } - class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>, - public DeclVisitor<ASTNodeImporter, Decl *>, - public StmtVisitor<ASTNodeImporter, Stmt *> { + // 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) @@ -147,16 +283,23 @@ 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. ToD = CreateFun(std::forward<Args>(args)...); + // Keep track of imported Decls. + Importer.MapImported(FromD, ToD); + Importer.AddToLookupTable(ToD); InitializeImportedDecl(FromD, ToD); return false; // A new Decl is created. } void InitializeImportedDecl(Decl *FromD, Decl *ToD) { - Importer.MapImported(FromD, ToD); ToD->IdentifierNamespace = FromD->IdentifierNamespace; if (FromD->hasAttrs()) for (const Attr *FromAttr : FromD->getAttrs()) @@ -170,84 +313,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); + 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); - bool ImportCastPath(CastExpr *E, CXXCastPath &Path); + 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 @@ -258,42 +399,44 @@ namespace clang { (IDK == IDK_Default && !Importer.isMinimalImport()); } - bool ImportDefinition(RecordDecl *From, RecordDecl *To, - ImportDefinitionKind Kind = IDK_Default); - bool ImportDefinition(VarDecl *From, VarDecl *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, @@ -307,257 +450,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); + 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); - 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( + 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 *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(); + + 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(); - return std::make_tuple(Template, ToTemplArgs); + 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 @@ -568,26 +952,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; @@ -627,183 +1015,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; @@ -811,112 +1212,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 @@ -927,293 +1324,287 @@ 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(); FunctionDecl *FunDecl; if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) && FunDecl->hasBody()) { - SourceRange RecR = D->getSourceRange(); - SourceRange BodyR = FunDecl->getBody()->getSourceRange(); - // If RecordDecl is not in Body (it is a param), we bail out. - if (RecR.isValid() && BodyR.isValid() && - (RecR.getBegin() < BodyR.getBegin() || - BodyR.getEnd() < RecR.getEnd())) { - Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) - << D->getDeclKindName(); - return true; + auto getLeafPointeeType = [](const Type *T) { + while (T->isPointerType() || T->isArrayType()) { + T = T->getPointeeOrArrayElementType(); + } + return T; + }; + for (const ParmVarDecl *P : FunDecl->parameters()) { + const Type *LeafT = + getLeafPointeeType(P->getType().getCanonicalType().getTypePtr()); + auto *RT = dyn_cast<RecordType>(LeafT); + if (RT && RT->getDecl() == D) { + Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) + << D->getDeclKindName(); + 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; + return Error::success(); - if (!ToD) { - ToD = Importer.Import(FromD); - if (!ToD) - return; - } + if (!ToD) + if (Error Err = importInto(ToD, FromD)) + return Err; - 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 (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()) { @@ -1223,76 +1614,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()); } - for (auto *From : FromDC->decls()) - Importer.Import(From); + return Error::success(); } -void ASTNodeImporter::ImportImplicitMethods( +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; + + return Error::success(); +} + +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(); @@ -1364,228 +1800,172 @@ 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::ImportDefinition(VarDecl *From, VarDecl *To, - ImportDefinitionKind Kind) { +Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) { if (To->getAnyInitializer()) - return false; + return Error::success(); - // FIXME: Can we really import any initializer? Alternatively, we could force - // ourselves to import every declaration of a variable and then only use - // getInit() here. - To->setInit(Importer.Import(const_cast<Expr *>(From->getAnyInitializer()))); + Expr *FromInit = From->getInit(); + if (!FromInit) + return Error::success(); - // FIXME: Other bits to merge? + ExpectedExpr ToInitOrErr = import(FromInit); + if (!ToInitOrErr) + return ToInitOrErr.takeError(); - return false; + To->setInit(*ToInitOrErr); + if (From->isInitKnownICE()) { + EvaluatedStmt *Eval = To->ensureEvaluatedStmt(); + Eval->CheckedICE = true; + Eval->IsICE = From->isInitICE(); + } + + // FIXME: Other bits to merge? + 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())); - } - } + 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(); - llvm_unreachable("Invalid template argument kind"); + return TemplateParameterList::Create( + Importer.getToContext(), + *ToTemplateLocOrErr, + *ToLAngleLocOrErr, + ToParams, + *ToRAngleLocOrErr, + ToRequiresClause); } -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); +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 @@ -1682,30 +2062,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); @@ -1713,7 +2094,7 @@ Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { return ToD; } -Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { +ExpectedDecl ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); @@ -1722,18 +2103,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 @@ -1744,29 +2130,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); @@ -1774,14 +2157,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; @@ -1796,8 +2179,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace(); } else { SmallVector<NamedDecl *, 4> ConflictingDecls; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Namespace)) continue; @@ -1815,15 +2197,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->getLocStart()), Loc, Name.getAsIdentifierInfo(), + *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), /*PrevDecl=*/nullptr)) return ToNamespace; ToNamespace->setLexicalDeclContext(LexicalDC); @@ -1840,43 +2228,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); @@ -1885,14 +2272,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; @@ -1902,15 +2290,21 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { 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); @@ -1921,28 +2315,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->getLocStart()); - + // 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()); @@ -1956,22 +2352,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; @@ -1981,8 +2378,7 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; @@ -1996,26 +2392,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); @@ -2023,48 +2416,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->getLocStart())) - : GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, - Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo())) - return ToLabel; + 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; - auto *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt())); - if (!Label) - return nullptr; + } 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(Label); + 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; @@ -2072,7 +2470,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; @@ -2080,19 +2480,18 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // We may already have an enum of the same name; try to find and match it. if (!DC->isFunctionOrMethod() && SearchName) { SmallVector<NamedDecl *, 4> ConflictingDecls; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls); + auto FoundDecls = + Importer.findDeclsInToCtx(DC, SearchName); for (auto *FoundDecl : FoundDecls) { 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); } @@ -2104,53 +2503,69 @@ 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->getLocStart()), + 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 = + DCXX->getDescribedClassTemplate() && + DCXX->getDescribedClassTemplate()->getFriendObjectKind() != + Decl::FOK_None; + } + // 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 && + // Friend template declaration must be imported on its own. + !IsFriendTemplate && // In contrast to a normal CXXRecordDecl, the implicit // CXXRecordDecl of ClassTemplateSpecializationDecl is its redeclaration. // The definition of the implicit CXXRecordDecl in this case is the // 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. @@ -2158,8 +2573,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; @@ -2167,19 +2582,19 @@ 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; + IDNS |= Decl::IDNS_Ordinary | Decl::IDNS_TagFriend; // We may already have a record of the same name; try to find and match it. - RecordDecl *AdoptDecl = nullptr; RecordDecl *PrevDecl = nullptr; if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls); - + auto FoundDecls = + Importer.findDeclsInToCtx(DC, SearchName); if (!FoundDecls.empty()) { // We're going to have to compare D against potentially conflicting Decls, so complete it. if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition()) @@ -2196,30 +2611,23 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Found = Tag->getDecl(); } - if (D->getDescribedTemplate()) { - if (auto *Template = dyn_cast<ClassTemplateDecl>(Found)) - Found = Template->getTemplatedDecl(); - else - continue; - } - if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) { - if (!SearchName) { + // Do not emit false positive diagnostic in case of unnamed + // struct/union and in case of anonymous structs. Would be false + // because there may be several anonymous/unnamed structs in a class. + // E.g. these are both valid: + // struct A { // unnamed structs + // struct { struct A *next; } entry0; + // struct { struct A *next; } entry1; + // }; + // struct X { struct { int a; }; struct { int b; }; }; // anon structs + if (!SearchName) if (!IsStructuralMatch(D, FoundRecord, false)) continue; - } - PrevDecl = FoundRecord; - - if (RecordDecl *FoundDef = FoundRecord->getDefinition()) { - if ((SearchName && !D->isCompleteDefinition()) - || (D->isCompleteDefinition() && - D->isAnonymousStructOrUnion() - == FoundDef->isAnonymousStructOrUnion() && - IsStructuralMatch(D, FoundDef))) { - // The record types structurally match, or the "from" translation - // unit only had a forward declaration anyway; call it the same - // function. + if (IsStructuralMatch(D, FoundRecord)) { + RecordDecl *FoundDef = FoundRecord->getDefinition(); + if (D->isThisDeclarationADefinition() && FoundDef) { // FIXME: Structural equivalence check should check for same // user-defined methods. Importer.MapImported(D, FoundDef); @@ -2227,178 +2635,178 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { auto *FoundCXX = dyn_cast<CXXRecordDecl>(FoundDef); assert(FoundCXX && "Record type mismatch"); - if (D->isCompleteDefinition() && !Importer.isMinimalImport()) + if (!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; } - } else if (!D->isCompleteDefinition()) { - // We have a forward declaration of this type, so adopt that forward - // declaration rather than building a new one. - - // If one or both can be completed from external storage then try one - // last time to complete and compare them before doing this. - - if (FoundRecord->hasExternalLexicalStorage() && - !FoundRecord->isCompleteDefinition()) - FoundRecord->getASTContext().getExternalSource()->CompleteType(FoundRecord); - if (D->hasExternalLexicalStorage()) - D->getASTContext().getExternalSource()->CompleteType(D); - - if (FoundRecord->isCompleteDefinition() && - D->isCompleteDefinition() && - !IsStructuralMatch(D, FoundRecord)) - continue; - - AdoptDecl = FoundRecord; - continue; - } else if (!SearchName) { - continue; + PrevDecl = FoundRecord->getMostRecentDecl(); + break; } } ConflictingDecls.push_back(FoundDecl); - } + } // for if (!ConflictingDecls.empty() && SearchName) { 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->getLocStart()); - if (!D2) { - CXXRecordDecl *D2CXX = nullptr; - if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { - if (DCXX->isLambda()) { - TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo()); - if (GetImportedOrCreateSpecialDecl( - D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), - DC, TInfo, 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); - } 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, - Name.getAsIdentifierInfo(), PrevDecl, - DelayTypeCreation)) - return D2CXX; - Importer.getToContext().getTypeDeclType( - D2CXX, dyn_cast<CXXRecordDecl>(DC)); - } else { - if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), - D->getTagKind(), DC, StartLoc, Loc, - Name.getAsIdentifierInfo(), - cast_or_null<CXXRecordDecl>(PrevDecl))) - return D2CXX; - } + RecordDecl *D2 = nullptr; + CXXRecordDecl *D2CXX = nullptr; + if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { + if (DCXX->isLambda()) { + auto TInfoOrErr = import(DCXX->getLambdaTypeInfo()); + if (!TInfoOrErr) + return TInfoOrErr.takeError(); + if (GetImportedOrCreateSpecialDecl( + D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), + DC, *TInfoOrErr, Loc, DCXX->isDependentLambda(), + DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) + return D2CXX; + 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 + const bool DelayTypeCreation = true; + if (GetImportedOrCreateDecl( + D2CXX, D, Importer.getToContext(), D->getTagKind(), DC, + *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), + cast_or_null<CXXRecordDecl>(PrevDecl), DelayTypeCreation)) + return D2CXX; + Importer.getToContext().getTypeDeclType( + D2CXX, dyn_cast<CXXRecordDecl>(DC)); + } else { + if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), + D->getTagKind(), DC, *BeginLocOrErr, Loc, + Name.getAsIdentifierInfo(), + cast_or_null<CXXRecordDecl>(PrevDecl))) + return D2CXX; + } - D2 = D2CXX; - D2->setAccess(D->getAccess()); - D2->setLexicalDeclContext(LexicalDC); - if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit()) - LexicalDC->addDeclInternal(D2); + D2 = D2CXX; + D2->setAccess(D->getAccess()); + D2->setLexicalDeclContext(LexicalDC); + if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit()) + LexicalDC->addDeclInternal(D2); - if (ClassTemplateDecl *FromDescribed = - DCXX->getDescribedClassTemplate()) { - auto *ToDescribed = cast_or_null<ClassTemplateDecl>( - Importer.Import(FromDescribed)); - if (!ToDescribed) - return nullptr; - D2CXX->setDescribedClassTemplate(ToDescribed); - if (!DCXX->isInjectedClassName()) { - // In a record describing a template the type should be an - // InjectedClassNameType (see Sema::CheckClassTemplate). Update the - // previously set type to the correct value here (ToDescribed is not - // available at record create). - // FIXME: The previous type is cleared but not removed from - // ASTContext's internal storage. - CXXRecordDecl *Injected = nullptr; - for (NamedDecl *Found : D2CXX->noload_lookup(Name)) { - auto *Record = dyn_cast<CXXRecordDecl>(Found); - if (Record && Record->isInjectedClassName()) { - Injected = Record; - break; - } - } - D2CXX->setTypeForDecl(nullptr); - Importer.getToContext().getInjectedClassNameType(D2CXX, - ToDescribed->getInjectedClassNameSpecialization()); - if (Injected) { - Injected->setTypeForDecl(nullptr); - Importer.getToContext().getTypeDeclType(Injected, D2CXX); + if (LexicalDC != DC && D->isInIdentifierNamespace(Decl::IDNS_TagFriend)) + DC->makeDeclVisibleInContext(D2); + + if (ClassTemplateDecl *FromDescribed = + DCXX->getDescribedClassTemplate()) { + 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 + // InjectedClassNameType (see Sema::CheckClassTemplate). Update the + // previously set type to the correct value here (ToDescribed is not + // available at record create). + // FIXME: The previous type is cleared but not removed from + // ASTContext's internal storage. + CXXRecordDecl *Injected = nullptr; + for (NamedDecl *Found : D2CXX->noload_lookup(Name)) { + auto *Record = dyn_cast<CXXRecordDecl>(Found); + if (Record && Record->isInjectedClassName()) { + Injected = Record; + break; } } - } else if (MemberSpecializationInfo *MemberInfo = + // Create an injected type for the whole redecl chain. + SmallVector<Decl *, 2> Redecls = + getCanonicalForwardRedeclChain(D2CXX); + for (auto *R : Redecls) { + auto *RI = cast<CXXRecordDecl>(R); + RI->setTypeForDecl(nullptr); + // Below we create a new injected type and assign that to the + // canonical decl, subsequent declarations in the chain will reuse + // that type. + Importer.getToContext().getInjectedClassNameType( + RI, ToDescribed->getInjectedClassNameSpecialization()); + } + // Set the new type for the previous injected decl too. + if (Injected) { + Injected->setTypeForDecl(nullptr); + Importer.getToContext().getTypeDeclType(Injected, D2CXX); + } + } + } else if (MemberSpecializationInfo *MemberInfo = DCXX->getMemberSpecializationInfo()) { 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())); - } - } else { - if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), - D->getTagKind(), DC, StartLoc, Loc, - Name.getAsIdentifierInfo(), PrevDecl)) - return D2; - D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(D2); + + 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(); } - D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); - if (D->isAnonymousStructOrUnion()) - D2->setAnonymousStructOrUnion(true); + } else { + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), + D->getTagKind(), DC, *BeginLocOrErr, Loc, + Name.getAsIdentifierInfo(), PrevDecl)) + return D2; + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(D2); } - Importer.MapImported(D, D2); + if (auto QualifierLocOrErr = import(D->getQualifierLoc())) + D2->setQualifierInfo(*QualifierLocOrErr); + else + return QualifierLocOrErr.takeError(); + + if (D->isAnonymousStructOrUnion()) + D2->setAnonymousStructOrUnion(true); - 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()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; @@ -2416,18 +2824,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()); @@ -2436,52 +2848,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: { @@ -2489,53 +2906,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. @@ -2543,8 +2963,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; @@ -2552,16 +2972,18 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { FunctionTemplateDecl *FromFT = D->getDescribedFunctionTemplate(); // If this is a function template specialization, then try to find the same - // existing specialization in the "to" context. The localUncachedLookup - // below will not find any specialization, but would find the primary - // template; thus, we have to skip normal lookup in case of specializations. + // existing specialization in the "to" context. The lookup below will not + // find any specialization, but would find the primary template; thus, we + // have to skip normal lookup in case of specializations. // 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; } } @@ -2570,20 +2992,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { else if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - // If template was found, look at the templated function. - if (FromFT) { - if (auto *Template = dyn_cast<FunctionTemplateDecl>(FoundDecl)) - FoundDecl = Template->getTemplatedDecl(); - else - continue; - } - if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) { if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { @@ -2622,13 +3035,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; @@ -2649,84 +3063,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->getLocEnd())); + ToFunction->setRangeEnd(ToEndLoc); // Set the parameters. for (auto *Param : Parameters) { @@ -2735,12 +3158,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) { @@ -2753,30 +3170,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); @@ -2796,133 +3216,139 @@ 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); } -static unsigned getFieldIndex(Decl *F) { - auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); - if (!Owner) - return 0; - - unsigned Index = 1; - for (const auto *D : Owner->noload_decls()) { - if (D == F) - return Index; - - if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) - ++Index; - } - - return Index; -} - -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; // Determine whether we've already imported this field. - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); 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 && getFieldIndex(D) != getFieldIndex(FoundField)) + if (!Name && + ASTImporter::getFieldIndex(D) != + ASTImporter::getFieldIndex(FoundField)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { Importer.MapImported(D, FoundField); + // In case of a FieldDecl of a ClassTemplateSpecializationDecl, the + // initializer of a FieldDecl might not had been instantiated in the + // "To" context. However, the "From" context might instantiated that, + // thus we have to merge that. + if (Expr *FromInitializer = D->getInClassInitializer()) { + // We don't have yet the initializer set. + if (FoundField->hasInClassInitializer() && + !FoundField->getInClassInitializer()) { + 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; + } + } + } 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; // Determine whether we've already imported this field. - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (auto *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { // For anonymous indirect fields, match up by index. - if (!Name && getFieldIndex(D) != getFieldIndex(FoundField)) + if (!Name && + ASTImporter::getFieldIndex(D) != + ASTImporter::getFieldIndex(FoundField)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), @@ -2936,39 +3362,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); @@ -2976,16 +3403,14 @@ 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. + // FriendDecl is not a NamedDecl so we cannot use lookup. auto *RD = cast<CXXRecordDecl>(DC); FriendDecl *ImportedFriend = RD->getFirstFriend(); @@ -3007,30 +3432,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()); @@ -3039,22 +3476,21 @@ 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; // Determine whether we've already imported this ivar - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); 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); @@ -3065,26 +3501,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); @@ -3092,25 +3529,36 @@ 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) { + ExpectedDecl RedeclOrErr = import(*RedeclIt); + if (!RedeclOrErr) + return RedeclOrErr.takeError(); + } + assert(*RedeclIt == 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; // Try to find a variable in our own ("to") context with the same name and // in the same context as the variable we're importing. + VarDecl *FoundByLookup = nullptr; if (D->isFileVarDecl()) { - VarDecl *MergeWithVar = nullptr; SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; @@ -3121,7 +3569,23 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { D->hasExternalFormalLinkage()) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundVar->getType())) { - MergeWithVar = FoundVar; + + // The VarDecl in the "From" context has a definition, but in the + // "To" context we already have a definition. + VarDecl *FoundDef = FoundVar->getDefinition(); + if (D->isThisDeclarationADefinition() && FoundDef) + // FIXME Check for ODR error if the two definitions have + // different initializers? + return Importer.MapImported(D, FoundDef); + + // The VarDecl in the "From" context has an initializer, but in the + // "To" context we already have an initializer. + const VarDecl *FoundDInit = nullptr; + if (D->getInit() && FoundVar->getAnyInitializer(FoundDInit)) + // FIXME Diagnose ODR error if the two initializers are different? + return Importer.MapImported(D, const_cast<VarDecl*>(FoundDInit)); + + FoundByLookup = FoundVar; break; } @@ -3133,16 +3597,16 @@ 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); - MergeWithVar = FoundVar; + FoundByLookup = FoundVar; break; } else if (isa<IncompleteArrayType>(TArray) && isa<ConstantArrayType>(FoundArray)) { - MergeWithVar = FoundVar; + FoundByLookup = FoundVar; break; } } @@ -3157,125 +3621,110 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { ConflictingDecls.push_back(FoundDecl); } - if (MergeWithVar) { - // An equivalent variable with external linkage has been found. Link - // the two declarations, then merge them. - Importer.MapImported(D, MergeWithVar); - updateFlags(D, MergeWithVar); - - if (VarDecl *DDef = D->getDefinition()) { - if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) { - Importer.ToDiag(ExistingDef->getLocation(), - diag::err_odr_variable_multiple_def) - << Name; - Importer.FromDiag(DDef->getLocation(), diag::note_odr_defined_here); - } else { - Expr *Init = Importer.Import(DDef->getInit()); - MergeWithVar->setInit(Init); - if (DDef->isInitKnownICE()) { - EvaluatedStmt *Eval = MergeWithVar->ensureEvaluatedStmt(); - Eval->CheckedICE = true; - Eval->IsICE = DDef->isInitICE(); - } - } - } - - return MergeWithVar; - } - if (!ConflictingDecls.empty()) { Name = Importer.HandleNameConflict(Name, DC, IDNS, 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); - // Templated declarations should never appear in the enclosing DeclContext. - if (!D->getDescribedVarTemplate()) - LexicalDC->addDeclInternal(ToVar); + if (FoundByLookup) { + auto *Recent = const_cast<VarDecl *>(FoundByLookup->getMostRecentDecl()); + ToVar->setPreviousDecl(Recent); + } - // Merge the initializer. - if (ImportDefinition(D, ToVar)) - return nullptr; + if (Error Err = ImportInitializer(D, ToVar)) + return std::move(Err); if (D->isConstexpr()) ToVar->setConstexpr(true); + if (D->getDeclContext()->containsDeclAndLoad(D)) + DC->addDeclInternal(ToVar); + if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) + LexicalDC->addDeclInternal(ToVar); + + // Import the rest of the chain. I.e. import all subsequent declarations. + 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; @@ -3283,21 +3732,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()); @@ -3310,19 +3757,18 @@ 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; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (auto *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecl)) { if (FoundMethod->isInstanceMethod() != D->isInstanceMethod()) @@ -3337,7 +3783,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. @@ -3348,7 +3795,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. @@ -3363,7 +3811,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); } } @@ -3375,7 +3824,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? @@ -3383,18 +3833,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->getLocEnd()), 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; @@ -3405,11 +3857,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. @@ -3418,82 +3869,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; @@ -3504,45 +3972,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 @@ -3551,17 +4022,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. @@ -3570,22 +4046,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. @@ -3593,14 +4069,13 @@ 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; ObjCProtocolDecl *MergeWithProtocol = nullptr; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) continue; @@ -3611,9 +4086,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); @@ -3622,29 +4101,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); @@ -3653,24 +4142,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; @@ -3679,48 +4175,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); @@ -3728,14 +4221,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); @@ -3743,32 +4235,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 ToComAncestorOrErr = Importer.ImportContext(D->getCommonAncestor()); + if (!ToComAncestorOrErr) + return ToComAncestorOrErr.takeError(); - auto *ToNominated = cast_or_null<NamespaceDecl>( - Importer.Import(D->getNominatedNamespace())); - if (!ToNominated) - return nullptr; + 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); @@ -3777,25 +4277,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()); @@ -3805,23 +4314,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()); @@ -3831,16 +4347,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(); @@ -3865,8 +4382,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. @@ -3874,28 +4392,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. @@ -3904,58 +4426,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. @@ -3963,15 +4493,14 @@ 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; // Look for an existing interface with the same name. ObjCInterfaceDecl *MergeWithIface = nullptr; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; @@ -3983,9 +4512,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; @@ -3993,91 +4526,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); @@ -4110,30 +4651,31 @@ 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; // Check whether we have already imported this property. - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (auto *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecl)) { // Check property types. @@ -4143,7 +4685,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.? @@ -4154,79 +4697,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; +ExpectedDecl +ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { + ObjCPropertyDecl *Property; + if (Error Err = importInto(Property, D->getPropertyDecl())) + return std::move(Err); - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - if (!DC) - return nullptr; - - // 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->getLocStart()), - Importer.Import(D->getLocation()), Property, + ToBeginLoc, + ToLocation, Property, D->getPropertyImplementation(), Ivar, - Importer.Import(D->getPropertyIvarDeclLoc()))) + ToPropertyIvarDeclLoc)) return ToImpl; ToImpl->setLexicalDeclContext(LexicalDC); @@ -4244,7 +4796,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 @@ -4258,7 +4811,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. @@ -4268,41 +4822,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->getLocStart()), 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. @@ -4310,36 +4869,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; } @@ -4354,19 +4916,18 @@ static ClassTemplateDecl *getDefinition(ClassTemplateDecl *D) { return TemplateWithDef; } -Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *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. - auto *Definition = - cast_or_null<CXXRecordDecl>(D->getTemplatedDecl()->getDefinition()); - if (Definition && Definition != D->getTemplatedDecl()) { - Decl *ImportedDef - = Importer.Import(Definition->getDescribedClassTemplate()); - if (!ImportedDef) - return nullptr; +ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { + bool IsFriend = D->getFriendObjectKind() != Decl::FOK_None; - return Importer.MapImported(D, ImportedDef); + // If this template 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. + ClassTemplateDecl *Definition = getDefinition(D); + if (Definition && Definition != D && !IsFriend) { + if (ExpectedDecl ImportedDefOrErr = import(Definition)) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); } // Import the major distinguishing characteristics of this class template. @@ -4374,40 +4935,33 @@ 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; + ClassTemplateDecl *FoundByLookup = nullptr; + // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { - if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary | + Decl::IDNS_TagFriend)) continue; Decl *Found = FoundDecl; - if (auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found)) { - - // The class to be imported is a definition. - if (D->isThisDeclarationADefinition()) { - // Lookup will find the fwd decl only if that is more recent than the - // definition. So, try to get the definition if that is available in - // the redecl chain. - ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate); - if (!TemplateWithDef) - continue; - FoundTemplate = TemplateWithDef; // Continue with the definition. - } + auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found); + if (FoundTemplate) { if (IsStructuralMatch(D, FoundTemplate)) { - // The class templates structurally match; call it the same template. - - Importer.MapImported(D->getTemplatedDecl(), - FoundTemplate->getTemplatedDecl()); - return Importer.MapImported(D, FoundTemplate); + ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate); + if (D->isThisDeclarationADefinition() && TemplateWithDef) { + return Importer.MapImported(D, TemplateWithDef); + } + FoundByLookup = FoundTemplate; + break; } } @@ -4421,33 +4975,61 @@ 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); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(D2); + + if (D->getDeclContext()->containsDeclAndLoad(D)) + DC->addDeclInternal(D2); + if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) + LexicalDC->addDeclInternal(D2); + + if (FoundByLookup) { + auto *Recent = + const_cast<ClassTemplateDecl *>(FoundByLookup->getMostRecentDecl()); + + // It is possible that during the import of the class template definition + // we start the import of a fwd friend decl of the very same class template + // and we add the fwd friend decl to the lookup table. But the ToTemplated + // had been created earlier and by that time the lookup could not find + // anything existing, so it has no previous decl. Later, (still during the + // import of the fwd friend decl) we start to import the definition again + // and this time the lookup finds the previous fwd friend class template. + // In this case we must set up the previous decl for the templated decl. + if (!ToTemplated->getPreviousDecl()) { + CXXRecordDecl *PrevTemplated = + FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); + if (ToTemplated != PrevTemplated) + ToTemplated->setPreviousDecl(PrevTemplated); + } + + D2->setPreviousDecl(Recent); + } + + if (LexicalDC != DC && IsFriend) + DC->makeDeclVisibleInContext(D2); if (FromTemplated->isCompleteDefinition() && !ToTemplated->isCompleteDefinition()) { @@ -4457,124 +5039,173 @@ 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->getLocStart()); - 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; - ClassTemplateSpecializationDecl *D2 - = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); - if (D2) { - // We already have a class template specialization with these template - // arguments. + ClassTemplateSpecializationDecl *D2 = nullptr; + ClassTemplatePartialSpecializationDecl *PartialSpec = + dyn_cast<ClassTemplatePartialSpecializationDecl>(D); + if (PartialSpec) + D2 = ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos); + else + D2 = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); + ClassTemplateSpecializationDecl * const PrevDecl = D2; + RecordDecl *FoundDef = D2 ? D2->getDefinition() : nullptr; + if (FoundDef) { + if (!D->isCompleteDefinition()) { + // The "From" translation unit only had a forward declaration; call it + // the same declaration. + // TODO Handle the redecl chain properly! + return Importer.MapImported(D, FoundDef); + } - // FIXME: Check for specialization vs. instantiation errors. + if (IsStructuralMatch(D, FoundDef)) { - if (RecordDecl *FoundDef = D2->getDefinition()) { - if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) { - // The record types structurally match, or the "from" translation - // unit only had a forward declaration anyway; call it the same - // function. - return Importer.MapImported(D, FoundDef); + Importer.MapImported(D, FoundDef); + + // 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()) { + 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()) { + auto ToOrErr = import(FromM); + if (!ToOrErr) + // FIXME: return the error? + consumeError(ToOrErr.takeError()); } + + // TODO Import instantiated default arguments. + // TODO Import instantiated exception specifications. + // + // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint what + // else could be fused during an AST merge. + + return FoundDef; } - } else { - // Create a new specialization. - if (auto *PartialSpec = - dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { - // Import TemplateArgumentListInfo + } 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, nullptr)) + ToTAInfo, CanonInjType, + cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) return D2; - } else { + // Update InsertPos, because preceding import calls may have invalidated + // it by adding new specializations. + if (!ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos)) + // Add this partial specialization to the class template. + ClassTemplate->AddPartialSpecialization( + cast<ClassTemplatePartialSpecializationDecl>(D2), InsertPos); + + } else { // Not a partial specialization. if (GetImportedOrCreateDecl( - D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, - IdLoc, ClassTemplate, TemplateArgs, /*PrevDecl=*/nullptr)) + D2, D, Importer.getToContext(), D->getTagKind(), DC, + *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs, + PrevDecl)) return D2; + + // Update InsertPos, because preceding import calls may have invalidated + // it by adding new specializations. + if (!ClassTemplate->findSpecialization(TemplateArgs, InsertPos)) + // Add this specialization to the class template. + ClassTemplate->AddSpecialization(D2, InsertPos); } D2->setSpecializationKind(D->getSpecializationKind()); - // Add this specialization to the class template. - ClassTemplate->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 (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()); @@ -4586,13 +5217,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 @@ -4600,11 +5232,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. @@ -4612,8 +5244,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; @@ -4621,14 +5253,13 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { assert(!DC->isFunctionOrMethod() && "Variable templates cannot be declared at function scope"); SmallVector<NamedDecl *, 4> ConflictingDecls; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) 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(), @@ -4647,29 +5278,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); @@ -4686,46 +5320,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->getLocStart()); - 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; @@ -4748,17 +5378,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. @@ -4767,41 +5398,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); @@ -4810,7 +5447,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); @@ -4822,25 +5462,21 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( D2->setAccess(D->getAccess()); } - // NOTE: isThisDeclarationADefinition() can return DeclarationOnly even if - // declaration has initializer. Should this be fixed in the AST?.. Anyway, - // we have to check the declaration for initializer - otherwise, it won't be - // imported. - if ((D->isThisDeclarationADefinition() || D->hasInit()) && - ImportDefinition(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; @@ -4849,13 +5485,13 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // type, and in the same context as the function we're importing. if (!LexicalDC->isFunctionOrMethod()) { unsigned IDNS = Decl::IDNS_Ordinary; - SmallVector<NamedDecl *, 2> FoundDecls; - DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { 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)) { @@ -4865,22 +5501,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); @@ -4895,2073 +5531,2189 @@ 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); +ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) { + Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node) + << S->getStmtClassName(); + return make_error<ImportError>(ImportError::UnsupportedConstruct); } -Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { - Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node) - << S->getStmtClassName(); - return nullptr; -} -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 (Error Err = ImportContainerChecked(S->outputs(), Exprs)) + return std::move(Err); - if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs())) - return nullptr; + if (Error Err = ImportArrayChecked( + S->inputs(), Exprs.begin() + S->getNumOutputs())) + return std::move(Err); - auto *AsmStr = cast_or_null<StringLiteral>( - Importer.Import(S->getAsmString())); - if (!AsmStr) - return nullptr; + 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())); + Importer.getToContext(), + *AsmLocOrErr, + S->isSimple(), + S->isVolatile(), + S->getNumOutputs(), + S->getNumInputs(), + Names.data(), + Constraints.data(), + Exprs.data(), + *AsmStrOrErr, + S->getNumClobbers(), + Clobbers.data(), + *RParenLocOrErr); } -Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) { - DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup()); - for (auto *ToD : ToDG) { - if (!ToD) - return nullptr; - } - SourceLocation ToStartLoc = Importer.Import(S->getStartLoc()); - SourceLocation ToEndLoc = Importer.Import(S->getEndLoc()); - return new (Importer.getToContext()) DeclStmt(ToDG, ToStartLoc, ToEndLoc); +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); } -Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) { - SourceLocation ToSemiLoc = Importer.Import(S->getSemiLoc()); - return new (Importer.getToContext()) NullStmt(ToSemiLoc, - S->hasLeadingEmptyMacro()); +ExpectedStmt ASTNodeImporter::VisitNullStmt(NullStmt *S) { + ExpectedSLoc ToSemiLocOrErr = import(S->getSemiLoc()); + if (!ToSemiLocOrErr) + return ToSemiLocOrErr.takeError(); + return new (Importer.getToContext()) NullStmt( + *ToSemiLocOrErr, S->hasLeadingEmptyMacro()); } -Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { +ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { SmallVector<Stmt *, 8> ToStmts(S->size()); - if (ImportContainerChecked(S->body(), ToStmts)) - return nullptr; + if (Error Err = ImportContainerChecked(S->body(), ToStmts)) + return std::move(Err); + + ExpectedSLoc ToLBracLocOrErr = import(S->getLBracLoc()); + if (!ToLBracLocOrErr) + return ToLBracLocOrErr.takeError(); + + 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(); + + SourceLocation ToDefaultLoc, ToColonLoc; + Stmt *ToSubStmt; + std::tie(ToDefaultLoc, ToColonLoc, ToSubStmt) = *Imp; + + return new (Importer.getToContext()) DefaultStmt( + ToDefaultLoc, ToColonLoc, ToSubStmt); } -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); +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::VisitAttributedStmt(AttributedStmt *S) { - SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc()); +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 (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); + 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); } -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::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); } -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::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); +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::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::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::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::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::VisitContinueStmt(ContinueStmt *S) { - SourceLocation ToContinueLoc = Importer.Import(S->getContinueLoc()); - return new (Importer.getToContext()) ContinueStmt(ToContinueLoc); +ExpectedStmt ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) { + ExpectedSLoc ToContinueLocOrErr = import(S->getContinueLoc()); + if (!ToContinueLocOrErr) + return ToContinueLocOrErr.takeError(); + return new (Importer.getToContext()) ContinueStmt(*ToContinueLocOrErr); } -Stmt *ASTNodeImporter::VisitBreakStmt(BreakStmt *S) { - SourceLocation ToBreakLoc = Importer.Import(S->getBreakLoc()); - return new (Importer.getToContext()) BreakStmt(ToBreakLoc); +ExpectedStmt ASTNodeImporter::VisitBreakStmt(BreakStmt *S) { + auto ToBreakLocOrErr = import(S->getBreakLoc()); + if (!ToBreakLocOrErr) + return ToBreakLocOrErr.takeError(); + return new (Importer.getToContext()) BreakStmt(*ToBreakLocOrErr); } -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::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::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::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); } -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::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 ToHandlerOrErr.takeError(); } - return CXXTryStmt::Create(Importer.getToContext(), ToTryLoc, ToTryBlock, - ToHandlers); + + return CXXTryStmt::Create( + Importer.getToContext(), *ToTryLocOrErr,*ToTryBlockOrErr, ToHandlers); } -Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { - 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(ToRange, ToBegin, ToEnd, - ToCond, ToInc, - ToLoopVar, ToBody, - ToForLoc, ToCoawaitLoc, - ToColonLoc, ToRParenLoc); +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); } -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, +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::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); +ExpectedStmt ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { + auto Imp = importSeq( + S->getAtCatchLoc(), S->getRParenLoc(), S->getCatchParamDecl(), + S->getCatchBody()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToAtCatchLoc, ToRParenLoc; + VarDecl *ToCatchParamDecl; + Stmt *ToCatchBody; + std::tie(ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody) = *Imp; + + 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) { - Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node) - << E->getStmtClassName(); - return nullptr; +ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { + Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node) + << E->getStmtClassName(); + 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->getLocStart())); +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->getLocStart()), 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::VisitCharacterLiteral(CharacterLiteral *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(); + + ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); + if (!ToSubExprOrErr) + return ToSubExprOrErr.takeError(); - return new (Importer.getToContext()) CharacterLiteral(E->getValue(), - E->getKind(), T, - Importer.Import(E->getLocation())); + return new (Importer.getToContext()) ImaginaryLiteral( + *ToSubExprOrErr, *ToTypeOrErr); } -Expr *ASTNodeImporter::VisitStringLiteral(StringLiteral *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(); - SmallVector<SourceLocation, 4> Locations(E->getNumConcatenated()); - ImportArray(E->tokloc_begin(), E->tokloc_end(), Locations.begin()); + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); - return StringLiteral::Create(Importer.getToContext(), E->getBytes(), - E->getKind(), E->isPascal(), T, - Locations.data(), Locations.size()); + return new (Importer.getToContext()) CharacterLiteral( + E->getValue(), E->getKind(), *ToTypeOrErr, *ToLocationOrErr); } -Expr *ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *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(); - TypeSourceInfo *TInfo = Importer.Import(E->getTypeSourceInfo()); - if (!TInfo) - return nullptr; + SmallVector<SourceLocation, 4> ToLocations(E->getNumConcatenated()); + if (Error Err = ImportArrayChecked( + E->tokloc_begin(), E->tokloc_end(), ToLocations.begin())) + return std::move(Err); - Expr *Init = Importer.Import(E->getInitializer()); - if (!Init) - return nullptr; + return StringLiteral::Create( + Importer.getToContext(), E->getBytes(), E->getKind(), E->isPascal(), + *ToTypeOrErr, ToLocations.data(), ToLocations.size()); +} + +ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + auto Imp = importSeq( + E->getLParenLoc(), E->getTypeSourceInfo(), E->getType(), + E->getInitializer()); + if (!Imp) + return Imp.takeError(); + + 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(); + + ExpectedSLoc ToRParenLocOrErr = import(E->getRParenLoc()); + if (!ToRParenLocOrErr) + return ToRParenLocOrErr.takeError(); - return new (Importer.getToContext()) ParenListExpr( - Importer.getToContext(), Importer.Import(E->getLParenLoc()), - Exprs, Importer.Import(E->getLParenLoc())); + 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; +ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { + auto Imp = importSeq( + E->getLHS(), E->getRHS(), E->getType(), 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; + 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; - - Expr *ToLHS = Importer.Import(E->getLHS()); - if (!ToLHS) - return nullptr; - - Expr *ToRHS = Importer.Import(E->getRHS()); - if (!ToRHS) - 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 *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; + 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 *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; + 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()); + ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr, + ToQuestionLoc, ToColonLoc, ToType, E->getValueKind(), + E->getObjectKind()); } -Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + auto Imp = importSeq( + E->getBeginLoc(), E->getQueriedTypeSourceInfo(), + E->getDimensionExpression(), E->getEndLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); - TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo()); - if (!ToQueried) - return nullptr; - - Expr *Dim = Importer.Import(E->getDimensionExpression()); - if (!Dim && E->getDimensionExpression()) - return nullptr; + 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->getLocStart()), E->getTrait(), ToQueried, - E->getValue(), Dim, Importer.Import(E->getLocEnd()), 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->getLocStart()), E->getTrait(), ToQueried, - E->getValue(), Importer.Import(E->getLocEnd()), 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; +ExpectedStmt ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + auto Imp = importSeq( + E->getLHS(), E->getRHS(), E->getType(), E->getRBracketLoc()); + 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 *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 *ToLHS, *ToRHS; + QualType ToType, ToComputationLHSType, ToComputationResultType; + SourceLocation ToOperatorLoc; + std::tie(ToLHS, ToRHS, ToType, ToComputationLHSType, ToComputationResultType, + ToOperatorLoc) = *Imp; - Expr *RHS = Importer.Import(E->getRHS()); - if (!RHS) - return nullptr; - - 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; +ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { + auto Imp1 = importSeq( + E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten()); + if (!Imp1) + return Imp1.takeError(); - Expr *SubExpr = Importer.Import(E->getSubExpr()); - if (!SubExpr) - return nullptr; + QualType ToType; + Expr *ToSubExpr; + TypeSourceInfo *ToTypeInfoAsWritten; + std::tie(ToType, ToSubExpr, ToTypeInfoAsWritten) = *Imp1; - TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten()); - if (!TInfo && E->getTypeInfoAsWritten()) - return nullptr; - - 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: - break; // just fall through - } - - auto *Named = cast<CXXNamedCastExpr>(E); - SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()), - RParenLoc = Importer.Import(Named->getRParenLoc()); - SourceRange Brackets = Importer.Import(Named->getAngleBrackets()); - - switch (E->getStmtClass()) { - case Stmt::CXXStaticCastExprClass: - return CXXStaticCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), E->getCastKind(), - SubExpr, &BasePath, TInfo, - ExprLoc, RParenLoc, Brackets); - - case Stmt::CXXDynamicCastExprClass: - return CXXDynamicCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), E->getCastKind(), - SubExpr, &BasePath, TInfo, - ExprLoc, RParenLoc, Brackets); - - case Stmt::CXXReinterpretCastExprClass: - return CXXReinterpretCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), E->getCastKind(), - SubExpr, &BasePath, TInfo, - ExprLoc, RParenLoc, Brackets); - - case Stmt::CXXConstCastExprClass: - return CXXConstCastExpr::Create(Importer.getToContext(), T, - E->getValueKind(), SubExpr, TInfo, ExprLoc, - RParenLoc, Brackets); - 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.getLocStart()), - Node.getArrayExprIndex(), - Importer.Import(Node.getLocEnd()))); + 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.getLocStart()), FD, - Importer.Import(Node.getLocEnd()))); + 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.getLocStart()), ToII, - Importer.Import(Node.getLocEnd()))); + 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(); + + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToOperatorLoc, ToRParenLoc; + std::tie(ToType, ToTypeSourceInfo, ToOperatorLoc, ToRParenLoc) = *Imp; - return OffsetOfExpr::Create(Importer.getToContext(), T, - Importer.Import(OE->getOperatorLoc()), - TInfo, Nodes, Exprs, - Importer.Import(OE->getRParenLoc())); + 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->getLocStart()), Importer.Import(E->getLocEnd())); + 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; + CXXConstructorDecl *ToConstructor; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceRange ToParenOrBraceRange; + std::tie(ToConstructor, ToType, ToTypeSourceInfo, ToParenOrBraceRange) = *Imp; - SmallVector<Expr *, 8> Args(CE->getNumArgs()); - if (ImportContainerChecked(CE->arguments(), Args)) - return nullptr; + SmallVector<Expr *, 8> ToArgs(E->getNumArgs()); + if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) + return std::move(Err); - auto *Ctor = cast_or_null<CXXConstructorDecl>( - Importer.Import(CE->getConstructor())); - if (!Ctor) - return nullptr; - - return new (Importer.getToContext()) CXXTemporaryObjectExpr( - Importer.getToContext(), Ctor, T, TInfo, Args, - Importer.Import(CE->getParenOrBraceRange()), CE->hadMultipleCandidates(), - CE->isListInitialization(), CE->isStdInitListInitialization(), - CE->requiresZeroInitialization()); + return CXXTemporaryObjectExpr::Create( + 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); + Importer.getToContext(), ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc, + Length, ToPartialArguments); } -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; +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(); - auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>( - Importer.Import(CE->getOperatorDelete())); - if (!OperatorDeleteDecl && CE->getOperatorDelete()) - return nullptr; + 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; - 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; + 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())); + return CXXNewExpr::Create( + Importer.getToContext(), E->isGlobalNew(), ToOperatorNew, + ToOperatorDelete, E->passAlignment(), E->doesUsualArrayDeleteWantSize(), + ToPlacementArgs, ToTypeIdParens, ToArraySize, E->getInitializationStyle(), + ToInitializer, ToType, ToAllocatedTypeSourceInfo, ToSourceRange, + ToDirectInitRange); } -Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; - - 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->getLocStart())); + 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())); + return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, + ToType, E->getValueKind(), ToRParenLoc); } -Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); - 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; + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); - return new (Importer.getToContext()) - CXXBoolLiteralExpr(E->getValue(), T, Importer.Import(E->getLocation())); + return new (Importer.getToContext()) CXXThisExpr( + *ToLocationOrErr, *ToTypeOrErr, E->isImplicit()); } +ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { + ExpectedType ToTypeOrErr = import(E->getType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); -Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { - QualType T = Importer.Import(E->getType()); - if (T.isNull()) - return nullptr; + ExpectedSLoc ToLocationOrErr = import(E->getLocation()); + if (!ToLocationOrErr) + return ToLocationOrErr.takeError(); - Expr *ToBase = Importer.Import(E->getBase()); - if (!ToBase && E->getBase()) - return nullptr; + return new (Importer.getToContext()) CXXBoolLiteralExpr( + E->getValue(), *ToTypeOrErr, *ToLocationOrErr); +} - auto *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl())); - if (!ToMember && E->getMemberDecl()) - return nullptr; +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(); - auto *ToDecl = - dyn_cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())); - if (!ToDecl && E->getFoundDecl().getDecl()) - return nullptr; + 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; + 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 NameInfo(Name, Importer.Import(E->getExprLoc())); - ImportDeclarationNameLoc(E->getNameInfo(), NameInfo); + DeclarationNameInfo ToNameInfo(ToDeclName, ToExprLoc); + if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) + return std::move(Err); - TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()), - Importer.Import(E->getRAngleLoc())); + 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()); + Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, + ToNameInfo, 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())); - // Import additional name location/type info. - ImportDeclarationNameLoc(E->getNameInfo(), NameInfo); +ExpectedStmt +ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { + auto Imp1 = importSeq( + E->getType(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getTemplateKeywordLoc()); + if (!Imp1) + return Imp1.takeError(); - QualType BaseType = Importer.Import(E->getType()); - if (!E->getType().isNull() && BaseType.isNull()) - return nullptr; + 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. + 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()); + return CXXOperatorCallExpr::Create( + 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 CallExpr::Create(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); - 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->getLocEnd()), - LE->containsUnexpandedParameterPack()); + 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, 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(); } - To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator()); - To->setValueDependent(ILE->isValueDependent()); - To->setInstantiationDependent(ILE->isInstantiationDependent()); + // Copy InitListExprBitfields, which are not handled in the ctor of + // InitListExpr. + 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; - - Expr *ToCommon = Importer.Import(E->getCommonExpr()); - if (!ToCommon && E->getCommonExpr()) - return nullptr; +ExpectedStmt ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { + auto Imp = importSeq(E->getType(), E->getCommonExpr(), E->getSubExpr()); + if (!Imp) + return Imp.takeError(); - Expr *ToSubExpr = Importer.Import(E->getSubExpr()); - if (!ToSubExpr && E->getSubExpr()) - return nullptr; + QualType ToType; + Expr *ToCommonExpr, *ToSubExpr; + std::tie(ToType, ToCommonExpr, ToSubExpr) = *Imp; - 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->getLocStart()), 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, 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 Imp = importSeq( + E->getType(), E->getExprLoc(), E->getParameter(), E->getReplacement()); + if (!Imp) + return Imp.takeError(); - auto *Param = cast_or_null<NonTypeTemplateParmDecl>( - Importer.Import(E->getParameter())); - if (!Param) - return nullptr; - - 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->getLocStart()), - E->getTrait(), ToArgs, Importer.Import(E->getLocEnd()), 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, ASTContext &FromContext, FileManager &FromFileManager, - bool MinimalImport) - : ToContext(ToContext), FromContext(FromContext), + bool MinimalImport, + ASTImporterLookupTable *LookupTable) + : LookupTable(LookupTable), ToContext(ToContext), FromContext(FromContext), ToFileManager(ToFileManager), FromFileManager(FromFileManager), Minimal(MinimalImport) { - ImportedDecls[FromContext.getTranslationUnitDecl()] - = ToContext.getTranslationUnitDecl(); + + ImportedDecls[FromContext.getTranslationUnitDecl()] = + ToContext.getTranslationUnitDecl(); } 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; +} + +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; +} + +ASTImporter::FoundDeclsTy +ASTImporter::findDeclsInToCtx(DeclContext *DC, DeclarationName Name) { + // We search in the redecl context because of transparent contexts. + // E.g. a simple C language enum is a transparent context: + // enum E { A, B }; + // Now if we had a global variable in the TU + // int A; + // then the enum constant 'A' and the variable 'A' violates ODR. + // We can diagnose this only if we search in the redecl context. + DeclContext *ReDC = DC->getRedeclContext(); + if (LookupTable) { + ASTImporterLookupTable::LookupResult LookupResult = + LookupTable->lookup(ReDC, Name); + return FoundDeclsTy(LookupResult.begin(), LookupResult.end()); + } else { + // FIXME Can we remove this kind of lookup? + // Or lldb really needs this C/C++ lookup? + FoundDeclsTy Result; + ReDC->localUncachedLookup(Name, Result); + return Result; + } +} + +void ASTImporter::AddToLookupTable(Decl *ToD) { + if (LookupTable) + if (auto *ToND = dyn_cast<NamedDecl>(ToD)) + LookupTable->add(ToND); +} + 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; @@ -6972,28 +7724,34 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { if (T.isNull()) return nullptr; - return ToContext.getTrivialTypeSourceInfo(T, - Import(FromTSI->getTypeLoc().getLocStart())); + return ToContext.getTrivialTypeSourceInfo( + 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; @@ -7009,17 +7767,26 @@ 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; + + // Once the decl is connected to the existing declarations, i.e. when the + // redecl chain is properly set then we populate the lookup again. + // This way the primary context will be able to find all decls. + AddToLookupTable(ToD); // Notify subclasses. Imported(FromD, ToD); + updateFlags(FromD, ToD); return ToD; } -DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { +Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) { if (!FromDC) return FromDC; @@ -7034,8 +7801,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); } @@ -7044,8 +7812,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); } @@ -7054,8 +7823,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); } @@ -7064,8 +7834,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); } @@ -7074,6 +7845,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; @@ -7081,6 +7858,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; @@ -7090,17 +7873,39 @@ 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>(*ToSOrErr)) { + auto *FromE = cast<Expr>(FromS); + // Copy ExprBitfields, which may not be handled in Expr subclasses + // constructors. + ToE->setValueKind(FromE->getValueKind()); + ToE->setObjectKind(FromE->getObjectKind()); + ToE->setTypeDependent(FromE->isTypeDependent()); + ToE->setValueDependent(FromE->isValueDependent()); + ToE->setInstantiationDependent(FromE->isInstantiationDependent()); + ToE->setContainsUnexpandedParameterPack( + FromE->containsUnexpandedParameterPack()); + } // 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; @@ -7154,6 +7959,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; @@ -7225,6 +8035,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: @@ -7301,18 +8117,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 {}; @@ -7327,10 +8151,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()) @@ -7388,6 +8222,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()) @@ -7433,6 +8274,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()) @@ -7448,50 +8296,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 {}; @@ -7568,6 +8428,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/ASTImporterLookupTable.cpp b/lib/AST/ASTImporterLookupTable.cpp new file mode 100644 index 000000000000..fbcd4f5cb341 --- /dev/null +++ b/lib/AST/ASTImporterLookupTable.cpp @@ -0,0 +1,129 @@ +//===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ASTImporterLookupTable class which implements a +// lookup procedure for the import mechanism. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTImporterLookupTable.h" +#include "clang/AST/Decl.h" +#include "clang/AST/RecursiveASTVisitor.h" + +namespace clang { + +namespace { + +struct Builder : RecursiveASTVisitor<Builder> { + ASTImporterLookupTable < + Builder(ASTImporterLookupTable <) : LT(LT) {} + bool VisitNamedDecl(NamedDecl *D) { + LT.add(D); + return true; + } + bool VisitFriendDecl(FriendDecl *D) { + if (D->getFriendType()) { + QualType Ty = D->getFriendType()->getType(); + // FIXME Can this be other than elaborated? + QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType(); + if (!NamedTy->isDependentType()) { + if (const auto *RTy = dyn_cast<RecordType>(NamedTy)) + LT.add(RTy->getAsCXXRecordDecl()); + else if (const auto *SpecTy = + dyn_cast<TemplateSpecializationType>(NamedTy)) { + LT.add(SpecTy->getAsCXXRecordDecl()); + } + } + } + return true; + } + + // Override default settings of base. + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } +}; + +} // anonymous namespace + +ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) { + Builder B(*this); + B.TraverseDecl(&TU); +} + +void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) { + DeclList &Decls = LookupTable[DC][ND->getDeclName()]; + // Inserts if and only if there is no element in the container equal to it. + Decls.insert(ND); +} + +void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) { + DeclList &Decls = LookupTable[DC][ND->getDeclName()]; + bool EraseResult = Decls.remove(ND); + (void)EraseResult; + assert(EraseResult == true && "Trying to remove not contained Decl"); +} + +void ASTImporterLookupTable::add(NamedDecl *ND) { + assert(ND); + DeclContext *DC = ND->getDeclContext()->getPrimaryContext(); + add(DC, ND); + DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext(); + if (DC != ReDC) + add(ReDC, ND); +} + +void ASTImporterLookupTable::remove(NamedDecl *ND) { + assert(ND); + DeclContext *DC = ND->getDeclContext()->getPrimaryContext(); + remove(DC, ND); + DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext(); + if (DC != ReDC) + remove(ReDC, ND); +} + +ASTImporterLookupTable::LookupResult +ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const { + auto DCI = LookupTable.find(DC->getPrimaryContext()); + if (DCI == LookupTable.end()) + return {}; + + const auto &FoundNameMap = DCI->second; + auto NamesI = FoundNameMap.find(Name); + if (NamesI == FoundNameMap.end()) + return {}; + + return NamesI->second; +} + +void ASTImporterLookupTable::dump(DeclContext *DC) const { + auto DCI = LookupTable.find(DC->getPrimaryContext()); + if (DCI == LookupTable.end()) + llvm::errs() << "empty\n"; + const auto &FoundNameMap = DCI->second; + for (const auto &Entry : FoundNameMap) { + DeclarationName Name = Entry.first; + llvm::errs() << "==== Name: "; + Name.dump(); + const DeclList& List = Entry.second; + for (NamedDecl *ND : List) { + ND->dump(); + } + } +} + +void ASTImporterLookupTable::dump() const { + for (const auto &Entry : LookupTable) { + DeclContext *DC = Entry.first; + StringRef Primary = DC->getPrimaryContext() ? " primary" : ""; + llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n"; + dump(DC); + } +} + +} // namespace clang diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index df3c2be9a2e2..d19b89bb95b4 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,14 +1016,15 @@ 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) return true; // If any of the records has external storage and we do a minimal check (or - // AST import) we assmue they are equivalent. (If we didn't have this + // AST import) we assume they are equivalent. (If we didn't have this // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger // another AST import which in turn would call the structural equivalency // check again and finally we'd have an improper result.) @@ -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() && @@ -1061,9 +1067,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); - Context.Diag2(Base2->getLocStart(), diag::note_odr_base) + Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base) << Base2->getType() << Base2->getSourceRange(); - Context.Diag1(Base1->getLocStart(), diag::note_odr_base) + Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base) << Base1->getType() << Base1->getSourceRange(); } return false; @@ -1075,9 +1081,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); - Context.Diag2(Base2->getLocStart(), diag::note_odr_virtual_base) + Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base) << Base2->isVirtual() << Base2->getSourceRange(); - Context.Diag1(Base1->getLocStart(), diag::note_odr_base) + Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base) << Base1->isVirtual() << Base1->getSourceRange(); } return false; @@ -1126,7 +1132,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.ToCtx.getTypeDeclType(D2); const CXXBaseSpecifier *Base1 = D1CXX->bases_begin(); - Context.Diag1(Base1->getLocStart(), diag::note_odr_base) + Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base) << Base1->getType() << Base1->getSourceRange(); Context.Diag2(D2->getLocation(), diag::note_odr_missing_base); } @@ -1178,6 +1184,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, /// Determine structural equivalence of two enums. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, EnumDecl *D1, EnumDecl *D2) { + + // Compare the definitions of these two enums. If either or both are + // incomplete (i.e. forward declared), we assume that they are equivalent. + D1 = D1->getDefinition(); + D2 = D2->getDefinition(); + if (!D1 || !D2) + return true; + EnumDecl::enumerator_iterator EC2 = D2->enumerator_begin(), EC2End = D2->enumerator_end(); for (EnumDecl::enumerator_iterator EC1 = D1->enumerator_begin(), @@ -1497,6 +1511,141 @@ bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) { return !Finish(); } +bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) { + // Check for equivalent described template. + TemplateDecl *Template1 = D1->getDescribedTemplate(); + TemplateDecl *Template2 = D2->getDescribedTemplate(); + if ((Template1 != nullptr) != (Template2 != nullptr)) + return false; + if (Template1 && !IsStructurallyEquivalent(*this, Template1, Template2)) + return false; + + // FIXME: Move check for identifier names into this function. + + return true; +} + +bool StructuralEquivalenceContext::CheckKindSpecificEquivalence( + Decl *D1, Decl *D2) { + // FIXME: Switch on all declaration kinds. For now, we're just going to + // check the obvious ones. + if (auto *Record1 = dyn_cast<RecordDecl>(D1)) { + if (auto *Record2 = dyn_cast<RecordDecl>(D2)) { + // Check for equivalent structure names. + IdentifierInfo *Name1 = Record1->getIdentifier(); + if (!Name1 && Record1->getTypedefNameForAnonDecl()) + Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier(); + IdentifierInfo *Name2 = Record2->getIdentifier(); + if (!Name2 && Record2->getTypedefNameForAnonDecl()) + Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier(); + if (!::IsStructurallyEquivalent(Name1, Name2) || + !::IsStructurallyEquivalent(*this, Record1, Record2)) + return false; + } else { + // Record/non-record mismatch. + return false; + } + } else if (auto *Enum1 = dyn_cast<EnumDecl>(D1)) { + if (auto *Enum2 = dyn_cast<EnumDecl>(D2)) { + // Check for equivalent enum names. + IdentifierInfo *Name1 = Enum1->getIdentifier(); + if (!Name1 && Enum1->getTypedefNameForAnonDecl()) + Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier(); + IdentifierInfo *Name2 = Enum2->getIdentifier(); + if (!Name2 && Enum2->getTypedefNameForAnonDecl()) + Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier(); + if (!::IsStructurallyEquivalent(Name1, Name2) || + !::IsStructurallyEquivalent(*this, Enum1, Enum2)) + return false; + } else { + // Enum/non-enum mismatch + return false; + } + } else if (const auto *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) { + if (const auto *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) { + if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(), + Typedef2->getIdentifier()) || + !::IsStructurallyEquivalent(*this, Typedef1->getUnderlyingType(), + Typedef2->getUnderlyingType())) + return false; + } else { + // Typedef/non-typedef mismatch. + return false; + } + } else if (auto *ClassTemplate1 = dyn_cast<ClassTemplateDecl>(D1)) { + if (auto *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, ClassTemplate1, + ClassTemplate2)) + return false; + } else { + // Class template/non-class-template mismatch. + return false; + } + } else if (auto *FunctionTemplate1 = dyn_cast<FunctionTemplateDecl>(D1)) { + if (auto *FunctionTemplate2 = dyn_cast<FunctionTemplateDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, FunctionTemplate1, + FunctionTemplate2)) + return false; + } else { + // Class template/non-class-template mismatch. + return false; + } + } else if (auto *TTP1 = dyn_cast<TemplateTypeParmDecl>(D1)) { + if (auto *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) + return false; + } else { + // Kind mismatch. + return false; + } + } else if (auto *NTTP1 = dyn_cast<NonTypeTemplateParmDecl>(D1)) { + if (auto *NTTP2 = dyn_cast<NonTypeTemplateParmDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2)) + return false; + } else { + // Kind mismatch. + return false; + } + } else if (auto *TTP1 = dyn_cast<TemplateTemplateParmDecl>(D1)) { + if (auto *TTP2 = dyn_cast<TemplateTemplateParmDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) + return false; + } else { + // Kind mismatch. + return false; + } + } else if (auto *MD1 = dyn_cast<CXXMethodDecl>(D1)) { + if (auto *MD2 = dyn_cast<CXXMethodDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, MD1, MD2)) + return false; + } else { + // Kind mismatch. + return false; + } + } else if (FunctionDecl *FD1 = dyn_cast<FunctionDecl>(D1)) { + if (FunctionDecl *FD2 = dyn_cast<FunctionDecl>(D2)) { + if (!::IsStructurallyEquivalent(FD1->getIdentifier(), + FD2->getIdentifier())) + return false; + if (!::IsStructurallyEquivalent(*this, FD1, FD2)) + return false; + } else { + // Kind mismatch. + return false; + } + } else if (FriendDecl *FrD1 = dyn_cast<FriendDecl>(D1)) { + if (FriendDecl *FrD2 = dyn_cast<FriendDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, FrD1, FrD2)) + return false; + } else { + // Kind mismatch. + return false; + } + } + + return true; +} + bool StructuralEquivalenceContext::Finish() { while (!DeclsToCheck.empty()) { // Check the next declaration. @@ -1506,123 +1655,8 @@ bool StructuralEquivalenceContext::Finish() { Decl *D2 = TentativeEquivalences[D1]; assert(D2 && "Unrecorded tentative equivalence?"); - bool Equivalent = true; - - // FIXME: Switch on all declaration kinds. For now, we're just going to - // check the obvious ones. - if (auto *Record1 = dyn_cast<RecordDecl>(D1)) { - if (auto *Record2 = dyn_cast<RecordDecl>(D2)) { - // Check for equivalent structure names. - IdentifierInfo *Name1 = Record1->getIdentifier(); - if (!Name1 && Record1->getTypedefNameForAnonDecl()) - Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier(); - IdentifierInfo *Name2 = Record2->getIdentifier(); - if (!Name2 && Record2->getTypedefNameForAnonDecl()) - Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2) || - !::IsStructurallyEquivalent(*this, Record1, Record2)) - Equivalent = false; - } else { - // Record/non-record mismatch. - Equivalent = false; - } - } else if (auto *Enum1 = dyn_cast<EnumDecl>(D1)) { - if (auto *Enum2 = dyn_cast<EnumDecl>(D2)) { - // Check for equivalent enum names. - IdentifierInfo *Name1 = Enum1->getIdentifier(); - if (!Name1 && Enum1->getTypedefNameForAnonDecl()) - Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier(); - IdentifierInfo *Name2 = Enum2->getIdentifier(); - if (!Name2 && Enum2->getTypedefNameForAnonDecl()) - Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2) || - !::IsStructurallyEquivalent(*this, Enum1, Enum2)) - Equivalent = false; - } else { - // Enum/non-enum mismatch - Equivalent = false; - } - } else if (const auto *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) { - if (const auto *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) { - if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(), - Typedef2->getIdentifier()) || - !::IsStructurallyEquivalent(*this, Typedef1->getUnderlyingType(), - Typedef2->getUnderlyingType())) - Equivalent = false; - } else { - // Typedef/non-typedef mismatch. - Equivalent = false; - } - } else if (auto *ClassTemplate1 = dyn_cast<ClassTemplateDecl>(D1)) { - if (auto *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, ClassTemplate1, - ClassTemplate2)) - Equivalent = false; - } else { - // Class template/non-class-template mismatch. - Equivalent = false; - } - } else if (auto *FunctionTemplate1 = dyn_cast<FunctionTemplateDecl>(D1)) { - if (auto *FunctionTemplate2 = dyn_cast<FunctionTemplateDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, FunctionTemplate1, - FunctionTemplate2)) - Equivalent = false; - } else { - // Class template/non-class-template mismatch. - Equivalent = false; - } - } else if (auto *TTP1 = dyn_cast<TemplateTypeParmDecl>(D1)) { - if (auto *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (auto *NTTP1 = dyn_cast<NonTypeTemplateParmDecl>(D1)) { - if (auto *NTTP2 = dyn_cast<NonTypeTemplateParmDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (auto *TTP1 = dyn_cast<TemplateTemplateParmDecl>(D1)) { - if (auto *TTP2 = dyn_cast<TemplateTemplateParmDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (auto *MD1 = dyn_cast<CXXMethodDecl>(D1)) { - if (auto *MD2 = dyn_cast<CXXMethodDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, MD1, MD2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (FunctionDecl *FD1 = dyn_cast<FunctionDecl>(D1)) { - if (FunctionDecl *FD2 = dyn_cast<FunctionDecl>(D2)) { - if (!::IsStructurallyEquivalent(FD1->getIdentifier(), - FD2->getIdentifier())) - Equivalent = false; - if (!::IsStructurallyEquivalent(*this, FD1, FD2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (FriendDecl *FrD1 = dyn_cast<FriendDecl>(D1)) { - if (FriendDecl *FrD2 = dyn_cast<FriendDecl>(D2)) { - if (!::IsStructurallyEquivalent(*this, FrD1, FrD2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } + bool Equivalent = + CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2); if (!Equivalent) { // Note that these two declarations are not equivalent (and we already @@ -1631,7 +1665,6 @@ bool StructuralEquivalenceContext::Finish() { std::make_pair(D1->getCanonicalDecl(), D2->getCanonicalDecl())); return true; } - // FIXME: Check other declaration kinds! } return false; diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 4f868a3af59e..570ca718acf5 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -10,6 +10,7 @@ add_clang_library(clangAST ASTDiagnostic.cpp ASTDumper.cpp ASTImporter.cpp + ASTImporterLookupTable.cpp ASTStructuralEquivalence.cpp ASTTypeTraits.cpp AttrImpl.cpp @@ -39,6 +40,7 @@ add_clang_library(clangAST ExprObjC.cpp ExternalASTMerger.cpp ExternalASTSource.cpp + FormatString.cpp InheritViz.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp @@ -48,12 +50,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 +70,7 @@ add_clang_library(clangAST StmtViz.cpp TemplateBase.cpp TemplateName.cpp + TextNodeDumper.cpp Type.cpp TypeLoc.cpp TypePrinter.cpp diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index a0b22b6a85e0..ddb350e72bbd 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -103,7 +103,6 @@ bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); - // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7. return lookupInBases( [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { return FindBaseClass(Specifier, Path, BaseDecl); @@ -124,7 +123,6 @@ bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const { Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); - // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7. return lookupInBases( [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { return FindVirtualBaseClass(Specifier, Path, BaseDecl); diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp index 8d401ff5c7ea..c43275318dd7 100644 --- a/lib/AST/CommentLexer.cpp +++ b/lib/AST/CommentLexer.cpp @@ -21,7 +21,7 @@ namespace comments { void Token::dump(const Lexer &L, const SourceManager &SM) const { llvm::errs() << "comments::Token Kind=" << Kind << " "; - Loc.dump(SM); + Loc.print(llvm::errs(), SM); llvm::errs() << " " << Length << " \"" << L.getSpelling(*this, SM) << "\"\n"; } diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp index c1c04239f58e..7f70b95e9812 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/CommentSema.cpp b/lib/AST/CommentSema.cpp index 4bc98bf10765..88588a7a89e6 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -703,10 +703,9 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) { SmallString<64> TextToInsert(" "); TextToInsert += AttributeSpelling; - Diag(FD->getLocEnd(), - diag::note_add_deprecation_attr) - << FixItHint::CreateInsertion(FD->getLocEnd().getLocWithOffset(1), - TextToInsert); + Diag(FD->getEndLoc(), diag::note_add_deprecation_attr) + << FixItHint::CreateInsertion(FD->getEndLoc().getLocWithOffset(1), + TextToInsert); } } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 8030dd0c2f41..5536358b1ecf 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 @@ -1262,7 +1262,27 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, !isTemplateInstantiation(FD->getTemplateSpecializationKind())) return LinkageInfo::none(); + // 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) && + !LV.isVisibilityExplicit()) { + assert(cast<VarDecl>(D)->isStaticLocal()); + // 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); + } + } } if (!isExternallyVisible(LV.getLinkage())) return LinkageInfo::none(); @@ -1937,7 +1957,7 @@ VarDecl::TLSKind VarDecl::getTLSKind() const { SourceRange VarDecl::getSourceRange() const { if (const Expr *Init = getInit()) { - SourceLocation InitEnd = Init->getLocEnd(); + SourceLocation InitEnd = Init->getEndLoc(); // If Init is implicit, ignore its source range and fallback on // DeclaratorDecl::getSourceRange() to handle postfix elements. if (InitEnd.isValid() && InitEnd != getLocation()) @@ -2351,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. @@ -2441,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; @@ -2449,6 +2477,12 @@ bool VarDecl::isKnownToBeDefined() const { return hasDefinition(); } +bool VarDecl::isNoDestroy(const ASTContext &Ctx) const { + return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() || + (!Ctx.getLangOpts().RegisterStaticDestructors && + !hasAttr<AlwaysDestroyAttr>())); +} + MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const { if (isStaticDataMember()) // FIXME: Remove ? @@ -2531,7 +2565,7 @@ SourceRange ParmVarDecl::getSourceRange() const { // DeclaratorDecl considers the range of postfix types as overlapping with the // declaration name, but this is not the case with parameters in ObjC methods. if (isa<ObjCMethodDecl>(getDeclContext())) - return SourceRange(DeclaratorDecl::getLocStart(), getLocation()); + return SourceRange(DeclaratorDecl::getBeginLoc(), getLocation()); return DeclaratorDecl::getSourceRange(); } @@ -2542,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; @@ -2609,6 +2643,41 @@ unsigned ParmVarDecl::getParameterIndexLarge() const { // FunctionDecl Implementation //===----------------------------------------------------------------------===// +FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, StorageClass S, + bool isInlineSpecified, bool isConstexprSpecified) + : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, + StartLoc), + DeclContext(DK), redeclarable_base(C), ODRHash(0), + EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) { + 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( raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); @@ -2672,11 +2741,11 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { void FunctionDecl::setBody(Stmt *B) { Body = B; if (B) - EndRangeLoc = B->getLocEnd(); + EndRangeLoc = B->getEndLoc(); } void FunctionDecl::setPure(bool P) { - IsPure = P; + FunctionDeclBits.IsPure = P; if (P) if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext())) Parent->markedVirtualFunctionPure(); @@ -2873,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>(); } @@ -2881,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); @@ -2892,8 +2976,8 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { FunTmpl->setPreviousDecl(PrevFunTmpl); } - if (PrevDecl && PrevDecl->IsInline) - IsInline = true; + if (PrevDecl && PrevDecl->isInlined()) + setImplicitlyInline(true); } FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } @@ -3127,7 +3211,7 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const { // Skip self-referential return types. const SourceManager &SM = getASTContext().getSourceManager(); SourceRange RTRange = FTL.getReturnLoc().getSourceRange(); - SourceLocation Boundary = getNameInfo().getLocStart(); + SourceLocation Boundary = getNameInfo().getBeginLoc(); if (RTRange.isInvalid() || Boundary.isInvalid() || !SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary)) return SourceRange(); @@ -3147,20 +3231,6 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const { return FTL.getExceptionSpecRange(); } -const Attr *FunctionDecl::getUnusedResultAttr() const { - QualType RetType = getReturnType(); - if (const auto *Ret = RetType->getAsRecordDecl()) { - if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>()) - return R; - } else if (const auto *ET = RetType->getAs<EnumType>()) { - if (const EnumDecl *ED = ET->getDecl()) { - if (const auto *R = ED->getAttr<WarnUnusedResultAttr>()) - return R; - } - } - return getAttr<WarnUnusedResultAttr>(); -} - /// For an inline function definition in C, or for a gnu_inline function /// in C++, determine whether the definition will be externally visible. /// @@ -3664,23 +3734,23 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { } unsigned FunctionDecl::getODRHash() const { - assert(HasODRHash); + assert(hasODRHash()); return ODRHash; } unsigned FunctionDecl::getODRHash() { - if (HasODRHash) + if (hasODRHash()) return ODRHash; if (auto *FT = getInstantiatedFromMemberFunction()) { - HasODRHash = true; + setHasODRHash(true); ODRHash = FT->getODRHash(); return ODRHash; } class ODRHash Hash; Hash.AddFunctionDecl(this); - HasODRHash = true; + setHasODRHash(true); ODRHash = Hash.CalculateHash(); return ODRHash; } @@ -3749,7 +3819,7 @@ SourceRange FieldDecl::getSourceRange() const { if (!FinalExpr) FinalExpr = getBitWidth(); if (FinalExpr) - return SourceRange(getInnerLocStart(), FinalExpr->getLocEnd()); + return SourceRange(getInnerLocStart(), FinalExpr->getEndLoc()); return DeclaratorDecl::getSourceRange(); } @@ -3767,6 +3837,22 @@ void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) { // TagDecl Implementation //===----------------------------------------------------------------------===// +TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl, + SourceLocation StartL) + : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C), + TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) { + assert((DK != Enum || TK == TTK_Enum) && + "EnumDecl not matched with TTK_Enum"); + setPreviousDecl(PrevDecl); + setTagKind(TK); + setCompleteDefinition(false); + setBeingDefined(false); + setEmbeddedInDeclarator(false); + setFreeStanding(false); + setCompleteDefinitionRequired(false); +} + SourceLocation TagDecl::getOuterLocStart() const { return getTemplateOrInnerLocStart(this); } @@ -3789,7 +3875,7 @@ void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { } void TagDecl::startDefinition() { - IsBeingDefined = true; + setBeingDefined(true); if (auto *D = dyn_cast<CXXRecordDecl>(this)) { struct CXXRecordDecl::DefinitionData *Data = @@ -3804,8 +3890,8 @@ void TagDecl::completeDefinition() { cast<CXXRecordDecl>(this)->hasDefinition()) && "definition completed but not started"); - IsCompleteDefinition = true; - IsBeingDefined = false; + setCompleteDefinition(true); + setBeingDefined(false); if (ASTMutationListener *L = getASTMutationListener()) L->CompletedTagDefinition(this); @@ -3816,7 +3902,7 @@ TagDecl *TagDecl::getDefinition() const { return const_cast<TagDecl *>(this); // If it's possible for us to have an out-of-date definition, check now. - if (MayHaveOutOfDateDef) { + if (mayHaveOutOfDateDef()) { if (IdentifierInfo *II = getIdentifier()) { if (II->isOutOfDate()) { updateOutOfDate(*II); @@ -3869,6 +3955,21 @@ void TagDecl::setTemplateParameterListsInfo( // EnumDecl Implementation //===----------------------------------------------------------------------===// +EnumDecl::EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, + bool Scoped, bool ScopedUsingClassTag, bool Fixed) + : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) { + assert(Scoped || !ScopedUsingClassTag); + IntegerType = nullptr; + setNumPositiveBits(0); + setNumNegativeBits(0); + setScoped(Scoped); + setScopedUsingClassTag(ScopedUsingClassTag); + setFixed(Fixed); + setHasODRHash(false); + ODRHash = 0; +} + void EnumDecl::anchor() {} EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, @@ -3878,7 +3979,7 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, bool IsScopedUsingClassTag, bool IsFixed) { auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl, IsScoped, IsScopedUsingClassTag, IsFixed); - Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; + Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules); C.getTypeDeclType(Enum, PrevDecl); return Enum; } @@ -3887,7 +3988,7 @@ EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { EnumDecl *Enum = new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr, false, false, false); - Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; + Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules); return Enum; } @@ -3971,12 +4072,12 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, } unsigned EnumDecl::getODRHash() { - if (HasODRHash) + if (hasODRHash()) return ODRHash; class ODRHash Hash; Hash.AddEnumDecl(this); - HasODRHash = true; + setHasODRHash(true); ODRHash = Hash.CalculateHash(); return ODRHash; } @@ -3989,14 +4090,18 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl) - : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc), - HasFlexibleArrayMember(false), AnonymousStructOrUnion(false), - HasObjectMember(false), HasVolatileMember(false), - LoadedFieldsFromExternalStorage(false), - NonTrivialToPrimitiveDefaultInitialize(false), - NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false), - ParamDestroyedInCallee(false), ArgPassingRestrictions(APK_CanPassInRegs) { - assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); + : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) { + assert(classof(static_cast<Decl *>(this)) && "Invalid Kind!"); + setHasFlexibleArrayMember(false); + setAnonymousStructOrUnion(false); + setHasObjectMember(false); + setHasVolatileMember(false); + setHasLoadedFieldsFromExternalStorage(false); + setNonTrivialToPrimitiveDefaultInitialize(false); + setNonTrivialToPrimitiveCopy(false); + setNonTrivialToPrimitiveDestroy(false); + setParamDestroyedInCallee(false); + setArgPassingRestrictions(APK_CanPassInRegs); } RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, @@ -4004,7 +4109,7 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, IdentifierInfo *Id, RecordDecl* PrevDecl) { RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl); - R->MayHaveOutOfDateDef = C.getLangOpts().Modules; + R->setMayHaveOutOfDateDef(C.getLangOpts().Modules); C.getTypeDeclType(R, PrevDecl); return R; @@ -4014,7 +4119,7 @@ RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { RecordDecl *R = new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); - R->MayHaveOutOfDateDef = C.getLangOpts().Modules; + R->setMayHaveOutOfDateDef(C.getLangOpts().Modules); return R; } @@ -4038,7 +4143,7 @@ void RecordDecl::setCapturedRecord() { } RecordDecl::field_iterator RecordDecl::field_begin() const { - if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage) + if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage()) LoadFieldsFromExternalStorage(); return field_iterator(decl_iterator(FirstDecl)); @@ -4066,7 +4171,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource::Deserializing TheFields(Source); SmallVector<Decl*, 64> Decls; - LoadedFieldsFromExternalStorage = true; + setHasLoadedFieldsFromExternalStorage(true); Source->FindExternalLexicalDecls(this, [](Decl::Kind K) { return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K); }, Decls); @@ -4148,6 +4253,15 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const { // BlockDecl Implementation //===----------------------------------------------------------------------===// +BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc) + : Decl(Block, DC, CaretLoc), DeclContext(Block) { + setIsVariadic(false); + setCapturesCXXThis(false); + setBlockMissingReturnType(true); + setIsConversionFromLambda(false); + setDoesNotEscape(false); +} + void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { assert(!ParamInfo && "Already has param info!"); @@ -4161,7 +4275,7 @@ void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures, bool CapturesCXXThis) { - this->CapturesCXXThis = CapturesCXXThis; + this->setCapturesCXXThis(CapturesCXXThis); this->NumCaptures = Captures.size(); if (Captures.empty()) { @@ -4182,7 +4296,7 @@ bool BlockDecl::capturesVariable(const VarDecl *variable) const { } SourceRange BlockDecl::getSourceRange() const { - return SourceRange(getLocation(), Body? Body->getLocEnd() : getLocation()); + return SourceRange(getLocation(), Body ? Body->getEndLoc() : getLocation()); } //===----------------------------------------------------------------------===// @@ -4315,7 +4429,7 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, FunctionDecl *New = new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, isInlineSpecified, isConstexprSpecified); - New->HasWrittenPrototype = hasWrittenPrototype; + New->setHasWrittenPrototype(hasWrittenPrototype); return New; } @@ -4398,7 +4512,7 @@ IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, SourceRange EnumConstantDecl::getSourceRange() const { SourceLocation End = getLocation(); if (Init) - End = Init->getLocEnd(); + End = Init->getEndLoc(); return SourceRange(getLocation(), End); } @@ -4472,14 +4586,14 @@ SourceRange TypedefDecl::getSourceRange() const { if (typeIsPostfix(TInfo->getType())) RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); } - return SourceRange(getLocStart(), RangeEnd); + return SourceRange(getBeginLoc(), RangeEnd); } SourceRange TypeAliasDecl::getSourceRange() const { - SourceLocation RangeEnd = getLocStart(); + SourceLocation RangeEnd = getBeginLoc(); if (TypeSourceInfo *TInfo = getTypeSourceInfo()) RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); - return SourceRange(getLocStart(), RangeEnd); + return SourceRange(getBeginLoc(), RangeEnd); } void FileScopeAsmDecl::anchor() {} diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 700ddd389ddd..b83082e9eb08 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -153,12 +153,12 @@ void Decl::setInvalidDecl(bool Invalid) { } const char *DeclContext::getDeclKindName() const { - switch (DeclKind) { - default: llvm_unreachable("Declaration context not in DeclNodes.inc!"); + switch (getDeclKind()) { #define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED; #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" } + llvm_unreachable("Declaration context not in DeclNodes.inc!"); } bool Decl::StatisticsEnabled = false; @@ -810,6 +810,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCCategoryImpl: case Import: case OMPThreadPrivate: + case OMPRequires: case OMPCapturedExpr: case Empty: // Never looked up by name. @@ -836,6 +837,29 @@ void Decl::dropAttrs() { getASTContext().eraseDeclAttrs(this); } +void Decl::addAttr(Attr *A) { + if (!hasAttrs()) { + setAttrs(AttrVec(1, A)); + return; + } + + AttrVec &Attrs = getAttrs(); + if (!A->isInherited()) { + Attrs.push_back(A); + return; + } + + // Attribute inheritance is processed after attribute parsing. To keep the + // order as in the source code, add inherited attributes before non-inherited + // ones. + auto I = Attrs.begin(), E = Attrs.end(); + for (; I != E; ++I) { + if (!(*I)->isInherited()) + break; + } + Attrs.insert(I, A); +} + const AttrVec &Decl::getAttrs() const { assert(HasAttrs && "No attrs to get!"); return getASTContext().getDeclAttrs(this); @@ -930,6 +954,10 @@ bool Decl::AccessDeclContextSanity() const { 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 { + return getASTContext().getAllocator().identifyKnownAlignedObject<Decl>(this); +} + const FunctionType *Decl::getFunctionType(bool BlocksToo) const { QualType Ty; if (const auto *D = dyn_cast<ValueDecl>(this)) @@ -980,6 +1008,16 @@ Decl *DeclContext::getNonClosureAncestor() { // DeclContext Implementation //===----------------------------------------------------------------------===// +DeclContext::DeclContext(Decl::Kind K) { + DeclContextBits.DeclKind = K; + setHasExternalLexicalStorage(false); + setHasExternalVisibleStorage(false); + setNeedToReconcileExternalVisibleStorage(false); + setHasLazyLocalLexicalLookups(false); + setHasLazyExternalLexicalLookups(false); + setUseQualifiedLookup(false); +} + bool DeclContext::classof(const Decl *D) { switch (D->getKind()) { #define DECL(NAME, BASE) @@ -1007,7 +1045,7 @@ DeclContext::~DeclContext() = default; /// a friend function the parent lookup context is the lexical context, which /// is the class in which the friend is declared. DeclContext *DeclContext::getLookupParent() { - // FIXME: Find a better way to identify friends + // FIXME: Find a better way to identify friends. if (isa<FunctionDecl>(this)) if (getParent()->getRedeclContext()->isFileContext() && getLexicalParent()->getRedeclContext()->isRecord()) @@ -1070,9 +1108,9 @@ bool DeclContext::isDependentContext() const { } bool DeclContext::isTransparentContext() const { - if (DeclKind == Decl::Enum) + if (getDeclKind() == Decl::Enum) return !cast<EnumDecl>(this)->isScoped(); - else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export) + else if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export) return true; return false; @@ -1118,7 +1156,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const { } DeclContext *DeclContext::getPrimaryContext() { - switch (DeclKind) { + switch (getDeclKind()) { case Decl::TranslationUnit: case Decl::ExternCContext: case Decl::LinkageSpec: @@ -1154,7 +1192,7 @@ DeclContext *DeclContext::getPrimaryContext() { return this; default: - if (DeclKind >= Decl::firstTag && DeclKind <= Decl::lastTag) { + if (getDeclKind() >= Decl::firstTag && getDeclKind() <= Decl::lastTag) { // If this is a tag type that has a definition or is currently // being defined, that definition is our primary context. auto *Tag = cast<TagDecl>(this); @@ -1174,7 +1212,8 @@ DeclContext *DeclContext::getPrimaryContext() { return Tag; } - assert(DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction && + assert(getDeclKind() >= Decl::firstFunction && + getDeclKind() <= Decl::lastFunction && "Unknown DeclContext kind"); return this; } @@ -1184,7 +1223,7 @@ void DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){ Contexts.clear(); - if (DeclKind != Decl::Namespace) { + if (getDeclKind() != Decl::Namespace) { Contexts.push_back(this); return; } @@ -1222,8 +1261,8 @@ DeclContext::BuildDeclChain(ArrayRef<Decl *> Decls, /// built a lookup map. For every name in the map, pull in the new names from /// the external storage. void DeclContext::reconcileExternalVisibleStorage() const { - assert(NeedToReconcileExternalVisibleStorage && LookupPtr); - NeedToReconcileExternalVisibleStorage = false; + assert(hasNeedToReconcileExternalVisibleStorage() && LookupPtr); + setNeedToReconcileExternalVisibleStorage(false); for (auto &Lookup : *LookupPtr) Lookup.second.setHasExternalDecls(); @@ -1242,7 +1281,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { // Load the external declarations, if any. SmallVector<Decl*, 64> Decls; - ExternalLexicalStorage = false; + setHasExternalLexicalStorage(false); Source->FindExternalLexicalDecls(this, Decls); if (Decls.empty()) @@ -1252,7 +1291,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { // we need to ignore them. bool FieldsAlreadyLoaded = false; if (const auto *RD = dyn_cast<RecordDecl>(this)) - FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage; + FieldsAlreadyLoaded = RD->hasLoadedFieldsFromExternalStorage(); // Splice the newly-read declarations into the beginning of the list // of declarations. @@ -1273,7 +1312,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, StoredDeclsMap *Map; if (!(Map = DC->LookupPtr)) Map = DC->CreateStoredDeclsMap(Context); - if (DC->NeedToReconcileExternalVisibleStorage) + if (DC->hasNeedToReconcileExternalVisibleStorage()) DC->reconcileExternalVisibleStorage(); (*Map)[Name].removeExternalDecls(); @@ -1289,7 +1328,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, StoredDeclsMap *Map; if (!(Map = DC->LookupPtr)) Map = DC->CreateStoredDeclsMap(Context); - if (DC->NeedToReconcileExternalVisibleStorage) + if (DC->hasNeedToReconcileExternalVisibleStorage()) DC->reconcileExternalVisibleStorage(); StoredDeclsList &List = (*Map)[Name]; @@ -1366,6 +1405,12 @@ static bool shouldBeHidden(NamedDecl *D) { D->isTemplateParameter()) return true; + // Skip friends and local extern declarations unless they're the first + // declaration of the entity. + if ((D->isLocalExternDecl() || D->getFriendObjectKind()) && + D != D->getCanonicalDecl()) + return true; + // Skip template specializations. // FIXME: This feels like a hack. Should DeclarationName support // template-ids, or is there a better way to keep specializations @@ -1424,7 +1469,9 @@ void DeclContext::removeDecl(Decl *D) { if (Map) { StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName()); assert(Pos != Map->end() && "no lookup entry for decl"); - if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND) + // Remove the decl only if it is contained. + StoredDeclsList::DeclsTy *Vec = Pos->second.getAsVector(); + if ((Vec && is_contained(*Vec, ND)) || Pos->second.getAsDecl() == ND) Pos->second.remove(ND); } } while (DC->isTransparentContext() && (DC = DC->getParent())); @@ -1483,21 +1530,24 @@ void DeclContext::addDeclInternal(Decl *D) { StoredDeclsMap *DeclContext::buildLookup() { assert(this == getPrimaryContext() && "buildLookup called on non-primary DC"); - if (!HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) + if (!hasLazyLocalLexicalLookups() && + !hasLazyExternalLexicalLookups()) return LookupPtr; SmallVector<DeclContext *, 2> Contexts; collectAllContexts(Contexts); - if (HasLazyExternalLexicalLookups) { - HasLazyExternalLexicalLookups = false; + if (hasLazyExternalLexicalLookups()) { + setHasLazyExternalLexicalLookups(false); for (auto *DC : Contexts) { - if (DC->hasExternalLexicalStorage()) - HasLazyLocalLexicalLookups |= - DC->LoadLexicalDeclsFromExternalStorage(); + if (DC->hasExternalLexicalStorage()) { + bool LoadedDecls = DC->LoadLexicalDeclsFromExternalStorage(); + setHasLazyLocalLexicalLookups( + hasLazyLocalLexicalLookups() | LoadedDecls ); + } } - if (!HasLazyLocalLexicalLookups) + if (!hasLazyLocalLexicalLookups()) return LookupPtr; } @@ -1505,7 +1555,7 @@ StoredDeclsMap *DeclContext::buildLookup() { buildLookupImpl(DC, hasExternalVisibleStorage()); // We no longer have any lazy decls. - HasLazyLocalLexicalLookups = false; + setHasLazyLocalLexicalLookups(false); return LookupPtr; } @@ -1543,7 +1593,8 @@ NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr; DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) const { - assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + assert(getDeclKind() != Decl::LinkageSpec && + getDeclKind() != Decl::Export && "should not perform lookups into transparent contexts"); const DeclContext *PrimaryContext = getPrimaryContext(); @@ -1560,12 +1611,13 @@ DeclContext::lookup(DeclarationName Name) const { if (hasExternalVisibleStorage()) { assert(Source && "external visible storage but no external source?"); - if (NeedToReconcileExternalVisibleStorage) + if (hasNeedToReconcileExternalVisibleStorage()) reconcileExternalVisibleStorage(); StoredDeclsMap *Map = LookupPtr; - if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups) + if (hasLazyLocalLexicalLookups() || + hasLazyExternalLexicalLookups()) // FIXME: Make buildLookup const? Map = const_cast<DeclContext*>(this)->buildLookup(); @@ -1590,7 +1642,8 @@ DeclContext::lookup(DeclarationName Name) const { } StoredDeclsMap *Map = LookupPtr; - if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups) + if (hasLazyLocalLexicalLookups() || + hasLazyExternalLexicalLookups()) Map = const_cast<DeclContext*>(this)->buildLookup(); if (!Map) @@ -1605,7 +1658,8 @@ DeclContext::lookup(DeclarationName Name) const { DeclContext::lookup_result DeclContext::noload_lookup(DeclarationName Name) { - assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + assert(getDeclKind() != Decl::LinkageSpec && + getDeclKind() != Decl::Export && "should not perform lookups into transparent contexts"); DeclContext *PrimaryContext = getPrimaryContext(); @@ -1626,12 +1680,12 @@ DeclContext::noload_lookup(DeclarationName Name) { // now. Don't import any external declarations, not even if we know we have // some missing from the external visible lookups. void DeclContext::loadLazyLocalLexicalLookups() { - if (HasLazyLocalLexicalLookups) { + if (hasLazyLocalLexicalLookups()) { SmallVector<DeclContext *, 2> Contexts; collectAllContexts(Contexts); for (auto *Context : Contexts) buildLookupImpl(Context, hasExternalVisibleStorage()); - HasLazyLocalLexicalLookups = false; + setHasLazyLocalLexicalLookups(false); } } @@ -1649,7 +1703,8 @@ void DeclContext::localUncachedLookup(DeclarationName Name, // If we have a lookup table, check there first. Maybe we'll get lucky. // FIXME: Should we be checking these flags on the primary context? - if (Name && !HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) { + if (Name && !hasLazyLocalLexicalLookups() && + !hasLazyExternalLexicalLookups()) { if (StoredDeclsMap *Map = LookupPtr) { StoredDeclsMap::iterator Pos = Map->find(Name); if (Pos != Map->end()) { @@ -1674,8 +1729,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; } @@ -1758,7 +1823,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, buildLookup(); makeDeclVisibleInContextImpl(D, Internal); } else { - HasLazyLocalLexicalLookups = true; + setHasLazyLocalLexicalLookups(true); } // If we are a transparent context or inline namespace, insert into our diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 51e8e14f804a..31ffeb0dcd1e 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -128,7 +128,7 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, bool DelayTypeCreation) { auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl); - R->MayHaveOutOfDateDef = C.getLangOpts().Modules; + R->setMayHaveOutOfDateDef(C.getLangOpts().Modules); // FIXME: DelayTypeCreation seems like such a hack if (!DelayTypeCreation) @@ -143,11 +143,11 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, LambdaCaptureDefault CaptureDefault) { auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc, nullptr, nullptr); - R->IsBeingDefined = true; + R->setBeingDefined(true); R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric, CaptureDefault); - R->MayHaveOutOfDateDef = false; + R->setMayHaveOutOfDateDef(false); R->setImplicit(true); C.getTypeDeclType(R, /*PrevDecl=*/nullptr); return R; @@ -158,7 +158,7 @@ CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { auto *R = new (C, ID) CXXRecordDecl( CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); - R->MayHaveOutOfDateDef = false; + R->setMayHaveOutOfDateDef(false); return R; } @@ -628,6 +628,24 @@ bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType( return false; } +bool CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable() const { + assert(isLambda() && "not a lambda"); + + // C++2a [expr.prim.lambda.capture]p11: + // The closure type associated with a lambda-expression has no default + // constructor if the lambda-expression has a lambda-capture and a + // defaulted default constructor otherwise. It has a deleted copy + // assignment operator if the lambda-expression has a lambda-capture and + // defaulted copy and move assignment operators otherwise. + // + // C++17 [expr.prim.lambda]p21: + // The closure type associated with a lambda-expression has no default + // constructor and a deleted copy assignment operator. + if (getLambdaCaptureDefault() != LCD_None) + return false; + return getASTContext().getLangOpts().CPlusPlus2a; +} + void CXXRecordDecl::addedMember(Decl *D) { if (!D->isImplicit() && !isa<FieldDecl>(D) && @@ -731,9 +749,14 @@ void CXXRecordDecl::addedMember(Decl *D) { } // C++11 [dcl.init.aggr]p1: DR1518 - // An aggregate is an array or a class with no user-provided, explicit, or - // inherited constructors - if (Constructor->isUserProvided() || Constructor->isExplicit()) + // An aggregate is an array or a class with no user-provided [or] + // explicit [...] constructors + // C++20 [dcl.init.aggr]p1: + // An aggregate is an array or a class with no user-declared [...] + // constructors + if (getASTContext().getLangOpts().CPlusPlus2a + ? !Constructor->isImplicit() + : (Constructor->isUserProvided() || Constructor->isExplicit())) data().Aggregate = false; } @@ -1327,6 +1350,15 @@ bool CXXRecordDecl::isGenericLambda() const { return getLambdaData().IsGenericLambda; } +#ifndef NDEBUG +static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) { + for (auto *D : R) + if (!declaresSameEntity(D, R.front())) + return false; + return true; +} +#endif + CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { if (!isLambda()) return nullptr; DeclarationName Name = @@ -1334,7 +1366,8 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { DeclContext::lookup_result Calls = lookup(Name); assert(!Calls.empty() && "Missing lambda call operator!"); - assert(Calls.size() == 1 && "More than one lambda call operator!"); + assert(allLookupResultsAreTheSame(Calls) && + "More than one lambda call operator!"); NamedDecl *CallOp = Calls.front(); if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp)) @@ -1349,7 +1382,8 @@ CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const { &getASTContext().Idents.get(getLambdaStaticInvokerName()); DeclContext::lookup_result Invoker = lookup(Name); if (Invoker.empty()) return nullptr; - assert(Invoker.size() == 1 && "More than one static invoker operator!"); + assert(allLookupResultsAreTheSame(Invoker) && + "More than one static invoker operator!"); NamedDecl *InvokerFun = Invoker.front(); if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(InvokerFun)) return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl()); @@ -1994,7 +2028,9 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, return nullptr; } -bool CXXMethodDecl::isUsualDeallocationFunction() const { +bool CXXMethodDecl::isUsualDeallocationFunction( + SmallVectorImpl<const FunctionDecl *> &PreventedBy) const { + assert(PreventedBy.empty() && "PreventedBy is expected to be empty"); if (getOverloadedOperator() != OO_Delete && getOverloadedOperator() != OO_Array_Delete) return false; @@ -2052,14 +2088,16 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const { // This function is a usual deallocation function if there are no // single-parameter deallocation functions of the same kind. DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName()); - for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end(); - I != E; ++I) { - if (const auto *FD = dyn_cast<FunctionDecl>(*I)) - if (FD->getNumParams() == 1) - return false; + bool Result = true; + for (const auto *D : R) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->getNumParams() == 1) { + PreventedBy.push_back(FD); + Result = false; + } + } } - - return true; + return Result; } bool CXXMethodDecl::isCopyAssignmentOperator() const { @@ -2135,19 +2173,24 @@ CXXMethodDecl::overridden_methods() const { return getASTContext().overridden_methods(this); } -QualType CXXMethodDecl::getThisType(ASTContext &C) const { +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() 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 { @@ -2208,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(); @@ -2246,6 +2294,21 @@ SourceRange CXXCtorInitializer::getSourceRange() const { return SourceRange(getSourceLocation(), getRParenLoc()); } +CXXConstructorDecl::CXXConstructorDecl( + ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared, + bool isConstexpr, InheritedConstructor Inherited) + : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, + SC_None, isInline, isConstexpr, SourceLocation()) { + setNumCtorInitializers(0); + setInheritingConstructor(static_cast<bool>(Inherited)); + setImplicit(isImplicitlyDeclared); + if (Inherited) + *getTrailingObjects<InheritedConstructor>() = Inherited; + setExplicitSpecified(isExplicitSpecified); +} + void CXXConstructorDecl::anchor() {} CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, @@ -2255,7 +2318,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, auto *Result = new (C, ID, Extra) CXXConstructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, false, false, false, false, InheritedConstructor()); - Result->IsInheritingConstructor = Inherited; + Result->setInheritingConstructor(Inherited); return Result; } @@ -2451,6 +2514,15 @@ bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { getConversionType()->isBlockPointerType(); } +LinkageSpecDecl::LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, + SourceLocation LangLoc, LanguageIDs lang, + bool HasBraces) + : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), + ExternLoc(ExternLoc), RBraceLoc(SourceLocation()) { + setLanguage(lang); + LinkageSpecDeclBits.HasBraces = HasBraces; +} + void LinkageSpecDecl::anchor() {} LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, @@ -2838,6 +2910,8 @@ void DecompositionDecl::printName(llvm::raw_ostream &os) const { os << ']'; } +void MSPropertyDecl::anchor() {} + MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 01fd10429fc1..1ed7fc71b025 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -65,6 +65,13 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts, // ObjCInterfaceDecl //===----------------------------------------------------------------------===// +ObjCContainerDecl::ObjCContainerDecl(Kind DK, DeclContext *DC, + IdentifierInfo *Id, SourceLocation nameLoc, + SourceLocation atStartLoc) + : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK) { + setAtStartLoc(atStartLoc); +} + void ObjCContainerDecl::anchor() {} /// getIvarDecl - This method looks up an ivar in this ContextDecl. @@ -350,7 +357,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const { SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const { if (TypeSourceInfo *superTInfo = getSuperClassTInfo()) - return superTInfo->getTypeLoc().getLocStart(); + return superTInfo->getTypeLoc().getBeginLoc(); return SourceLocation(); } @@ -769,6 +776,37 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( // ObjCMethodDecl //===----------------------------------------------------------------------===// +ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, + Selector SelInfo, QualType T, + TypeSourceInfo *ReturnTInfo, + DeclContext *contextDecl, bool isInstance, + bool isVariadic, bool isPropertyAccessor, + bool isImplicitlyDeclared, bool isDefined, + ImplementationControl impControl, + bool HasRelatedResultType) + : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), + DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo), + DeclEndLoc(endLoc) { + + // Initialized the bits stored in DeclContext. + ObjCMethodDeclBits.Family = + static_cast<ObjCMethodFamily>(InvalidObjCMethodFamily); + setInstanceMethod(isInstance); + setVariadic(isVariadic); + setPropertyAccessor(isPropertyAccessor); + setDefined(isDefined); + setIsRedeclaration(false); + setHasRedeclaration(false); + setDeclImplementation(impControl); + setObjCDeclQualifier(OBJC_TQ_None); + setRelatedResultType(HasRelatedResultType); + setSelLocsKind(SelLoc_StandardNoSpace); + setOverriding(false); + setHasSkippedBody(false); + + setImplicit(isImplicitlyDeclared); +} + ObjCMethodDecl *ObjCMethodDecl::Create( ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, @@ -791,6 +829,14 @@ bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const { hasAttr<ObjCDesignatedInitializerAttr>(); } +bool ObjCMethodDecl::definedInNSObject(const ASTContext &Ctx) const { + if (const auto *PD = dyn_cast<const ObjCProtocolDecl>(getDeclContext())) + return PD->getIdentifier() == Ctx.getNSObjectName(); + if (const auto *ID = dyn_cast<const ObjCInterfaceDecl>(getDeclContext())) + return ID->getIdentifier() == Ctx.getNSObjectName(); + return false; +} + bool ObjCMethodDecl::isDesignatedInitializerForTheInterface( const ObjCMethodDecl **InitMethod) const { if (getMethodFamily() != OMF_init) @@ -810,8 +856,8 @@ Stmt *ObjCMethodDecl::getBody() const { void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) { assert(PrevMethod); getASTContext().setObjCMethodRedeclaration(PrevMethod, this); - IsRedeclaration = true; - PrevMethod->HasRedeclaration = true; + setIsRedeclaration(true); + PrevMethod->setHasRedeclaration(true); } void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, @@ -846,9 +892,9 @@ void ObjCMethodDecl::setMethodParams(ASTContext &C, if (isImplicit()) return setParamsAndSelLocs(C, Params, llvm::None); - SelLocsKind = hasStandardSelectorLocs(getSelector(), SelLocs, Params, - DeclEndLoc); - if (SelLocsKind != SelLoc_NonStandard) + setSelLocsKind(hasStandardSelectorLocs(getSelector(), SelLocs, Params, + DeclEndLoc)); + if (getSelLocsKind() != SelLoc_NonStandard) return setParamsAndSelLocs(C, Params, llvm::None); setParamsAndSelLocs(C, Params, SelLocs); @@ -860,7 +906,7 @@ void ObjCMethodDecl::setMethodParams(ASTContext &C, ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { ASTContext &Ctx = getASTContext(); ObjCMethodDecl *Redecl = nullptr; - if (HasRedeclaration) + if (hasRedeclaration()) Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this)); if (Redecl) return Redecl; @@ -931,14 +977,14 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { return this; } -SourceLocation ObjCMethodDecl::getLocEnd() const { +SourceLocation ObjCMethodDecl::getEndLoc() const { if (Stmt *Body = getBody()) - return Body->getLocEnd(); + return Body->getEndLoc(); return DeclEndLoc; } ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { - auto family = static_cast<ObjCMethodFamily>(Family); + auto family = static_cast<ObjCMethodFamily>(ObjCMethodDeclBits.Family); if (family != static_cast<unsigned>(InvalidObjCMethodFamily)) return family; @@ -954,7 +1000,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break; case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break; } - Family = static_cast<unsigned>(family); + ObjCMethodDeclBits.Family = family; return family; } @@ -1025,7 +1071,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { } // Cache the result. - Family = static_cast<unsigned>(family); + ObjCMethodDeclBits.Family = family; return family; } diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp index f5c3599ef6c6..b77a67cbf38d 100644 --- a/lib/AST/DeclOpenMP.cpp +++ b/lib/AST/DeclOpenMP.cpp @@ -54,9 +54,49 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) { } //===----------------------------------------------------------------------===// +// OMPRequiresDecl Implementation. +//===----------------------------------------------------------------------===// + +void OMPRequiresDecl::anchor() {} + +OMPRequiresDecl *OMPRequiresDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + ArrayRef<OMPClause *> CL) { + OMPRequiresDecl *D = + new (C, DC, additionalSizeToAlloc<OMPClause *>(CL.size())) + OMPRequiresDecl(OMPRequires, DC, L); + D->NumClauses = CL.size(); + D->setClauses(CL); + return D; +} + +OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned N) { + OMPRequiresDecl *D = new (C, ID, additionalSizeToAlloc<OMPClause *>(N)) + OMPRequiresDecl(OMPRequires, nullptr, SourceLocation()); + D->NumClauses = N; + return D; +} + +void OMPRequiresDecl::setClauses(ArrayRef<OMPClause *> CL) { + assert(CL.size() == NumClauses && + "Number of clauses is not the same as the preallocated buffer"); + std::uninitialized_copy(CL.begin(), CL.end(), + getTrailingObjects<OMPClause *>()); +} + +//===----------------------------------------------------------------------===// // OMPDeclareReductionDecl Implementation. //===----------------------------------------------------------------------===// +OMPDeclareReductionDecl::OMPDeclareReductionDecl( + Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, + QualType Ty, OMPDeclareReductionDecl *PrevDeclInScope) + : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr), + PrevDeclInScope(PrevDeclInScope) { + setInitializer(nullptr, CallInit); +} + void OMPDeclareReductionDecl::anchor() {} OMPDeclareReductionDecl *OMPDeclareReductionDecl::Create( @@ -104,5 +144,5 @@ OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C, SourceRange OMPCapturedExprDecl::getSourceRange() const { assert(hasInit()); - return SourceRange(getInit()->getLocStart(), getInit()->getLocEnd()); + return SourceRange(getInit()->getBeginLoc(), getInit()->getEndLoc()); } diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 09e22f19f87a..517851f9eeb1 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -100,6 +100,7 @@ namespace { void VisitUsingDecl(UsingDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); + void VisitOMPRequiresDecl(OMPRequiresDecl *D); void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); @@ -422,7 +423,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { // FIXME: Need to be able to tell the DeclPrinter when const char *Terminator = nullptr; - if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D)) + if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) || + isa<OMPRequiresDecl>(*D)) Terminator = nullptr; else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody()) Terminator = nullptr; @@ -544,7 +546,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { prettyPrintAttributes(D); if (Expr *Init = D->getInitExpr()) { Out << " = "; - Init->printPretty(Out, nullptr, Policy, Indentation, &Context); + Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); } } @@ -1091,6 +1093,10 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { printTemplateParameters(FD->getTemplateParameterList(I)); } VisitRedeclarableTemplateDecl(D); + // Declare target attribute is special one, natural spelling for the pragma + // assumes "ending" construct so print it here. + if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>()) + Out << "#pragma omp end declare target\n"; // Never print "instantiations" for deduction guides (they don't really // have them). @@ -1540,6 +1546,15 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { } } +void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { + Out << "#pragma omp requires "; + if (!D->clauselist_empty()) { + OMPClausePrinter Printer(Out, Policy); + for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I) + Printer.Visit(*I); + } +} + void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { if (!D->isInvalidDecl()) { Out << "#pragma omp declare reduction ("; diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 848427e7f9d9..76f29dac1647 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -149,6 +149,8 @@ void *allocateDefaultArgStorageChain(const ASTContext &C) { // RedeclarableTemplateDecl Implementation //===----------------------------------------------------------------------===// +void RedeclarableTemplateDecl::anchor() {} + RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const { if (Common) return Common; @@ -300,6 +302,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 //===----------------------------------------------------------------------===// @@ -473,7 +509,7 @@ SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { SourceRange TemplateTypeParmDecl::getSourceRange() const { if (hasDefaultArgument() && !defaultArgumentWasInherited()) - return SourceRange(getLocStart(), + return SourceRange(getBeginLoc(), getDefaultArgumentInfo()->getTypeLoc().getEndLoc()); else return TypeDecl::getSourceRange(); @@ -712,7 +748,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, new (Context, DC) ClassTemplateSpecializationDecl( Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc, SpecializedTemplate, Args, PrevDecl); - Result->MayHaveOutOfDateDef = false; + Result->setMayHaveOutOfDateDef(false); Context.getTypeDeclType(Result, PrevDecl); return Result; @@ -723,7 +759,7 @@ ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { auto *Result = new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization); - Result->MayHaveOutOfDateDef = false; + Result->setMayHaveOutOfDateDef(false); return Result; } @@ -830,7 +866,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, Params, SpecializedTemplate, Args, ASTArgInfos, PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); - Result->MayHaveOutOfDateDef = false; + Result->setMayHaveOutOfDateDef(false); Context.getInjectedClassNameType(Result, CanonInjectedType); return Result; @@ -840,7 +876,7 @@ ClassTemplatePartialSpecializationDecl * ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C); - Result->MayHaveOutOfDateDef = false; + Result->setMayHaveOutOfDateDef(false); return Result; } diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 9866d92f61eb..f2c152f918eb 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -39,74 +39,6 @@ using namespace clang; -namespace clang { - -/// CXXSpecialName - Records the type associated with one of the -/// "special" kinds of declaration names in C++, e.g., constructors, -/// destructors, and conversion functions. -class CXXSpecialName - : public DeclarationNameExtra, public llvm::FoldingSetNode { -public: - /// Type - The type associated with this declaration name. - QualType Type; - - /// FETokenInfo - Extra information associated with this declaration - /// name that can be used by the front end. - void *FETokenInfo; - - void Profile(llvm::FoldingSetNodeID &ID) { - ID.AddInteger(ExtraKindOrNumArgs); - ID.AddPointer(Type.getAsOpaquePtr()); - } -}; - -/// Contains extra information for the name of a C++ deduction guide. -class CXXDeductionGuideNameExtra : public DeclarationNameExtra, - public llvm::FoldingSetNode { -public: - /// The template named by the deduction guide. - TemplateDecl *Template; - - /// FETokenInfo - Extra information associated with this operator - /// name that can be used by the front end. - void *FETokenInfo; - - void Profile(llvm::FoldingSetNodeID &ID) { - ID.AddPointer(Template); - } -}; - -/// CXXOperatorIdName - Contains extra information for the name of an -/// overloaded operator in C++, such as "operator+. -class CXXOperatorIdName : public DeclarationNameExtra { -public: - /// FETokenInfo - Extra information associated with this operator - /// name that can be used by the front end. - void *FETokenInfo; -}; - -/// CXXLiteralOperatorName - Contains the actual identifier that makes up the -/// name. -/// -/// This identifier is stored here rather than directly in DeclarationName so as -/// to allow Objective-C selectors, which are about a million times more common, -/// to consume minimal memory. -class CXXLiteralOperatorIdName - : public DeclarationNameExtra, public llvm::FoldingSetNode { -public: - IdentifierInfo *ID; - - /// FETokenInfo - Extra information associated with this operator - /// name that can be used by the front end. - void *FETokenInfo; - - void Profile(llvm::FoldingSetNodeID &FSID) { - FSID.AddPointer(ID); - } -}; - -} // namespace clang - static int compareInt(unsigned A, unsigned B) { return (A < B ? -1 : (A > B ? 1 : 0)); } @@ -117,10 +49,12 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { switch (LHS.getNameKind()) { case DeclarationName::Identifier: { - IdentifierInfo *LII = LHS.getAsIdentifierInfo(); - IdentifierInfo *RII = RHS.getAsIdentifierInfo(); - if (!LII) return RII ? -1 : 0; - if (!RII) return 1; + IdentifierInfo *LII = LHS.castAsIdentifierInfo(); + IdentifierInfo *RII = RHS.castAsIdentifierInfo(); + if (!LII) + return RII ? -1 : 0; + if (!RII) + return 1; return LII->getName().compare(RII->getName()); } @@ -134,15 +68,18 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector && RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) { return LHSSelector.getAsIdentifierInfo()->getName().compare( - RHSSelector.getAsIdentifierInfo()->getName()); + RHSSelector.getAsIdentifierInfo()->getName()); } unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs(); for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) { switch (LHSSelector.getNameForSlot(I).compare( - RHSSelector.getNameForSlot(I))) { - case -1: return -1; - case 1: return 1; - default: break; + RHSSelector.getNameForSlot(I))) { + case -1: + return -1; + case 1: + return 1; + default: + break; } } @@ -170,7 +107,7 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { case DeclarationName::CXXLiteralOperatorName: return LHS.getCXXLiteralIdentifier()->getName().compare( - RHS.getCXXLiteralIdentifier()->getName()); + RHS.getCXXLiteralIdentifier()->getName()); case DeclarationName::CXXUsingDirective: return 0; @@ -199,25 +136,24 @@ static void printCXXConstructorDestructorName(QualType ClassType, } void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { - DeclarationName &N = *this; - switch (N.getNameKind()) { + switch (getNameKind()) { case DeclarationName::Identifier: - if (const IdentifierInfo *II = N.getAsIdentifierInfo()) + if (const IdentifierInfo *II = getAsIdentifierInfo()) OS << II->getName(); return; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - N.getObjCSelector().print(OS); + getObjCSelector().print(OS); return; case DeclarationName::CXXConstructorName: - return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); + return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); case DeclarationName::CXXDestructorName: OS << '~'; - return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); + return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); case DeclarationName::CXXDeductionGuideName: OS << "<deduction guide for "; @@ -226,13 +162,13 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { return; case DeclarationName::CXXOperatorName: { - static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = { - nullptr, -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - Spelling, + static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = { + nullptr, +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + Spelling, #include "clang/Basic/OperatorKinds.def" }; - const char *OpName = OperatorNames[N.getCXXOverloadedOperator()]; + const char *OpName = OperatorNames[getCXXOverloadedOperator()]; assert(OpName && "not an overloaded operator"); OS << "operator"; @@ -243,12 +179,12 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { } case DeclarationName::CXXLiteralOperatorName: - OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName(); + OS << "operator\"\"" << getCXXLiteralIdentifier()->getName(); return; case DeclarationName::CXXConversionFunctionName: { OS << "operator "; - QualType Type = N.getCXXNameType(); + QualType Type = getCXXNameType(); if (const RecordType *Rec = Type->getAs<RecordType>()) { OS << *Rec->getDecl(); return; @@ -277,46 +213,6 @@ raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { } // namespace clang -DeclarationName::NameKind DeclarationName::getNameKind() const { - switch (getStoredNameKind()) { - case StoredIdentifier: return Identifier; - case StoredObjCZeroArgSelector: return ObjCZeroArgSelector; - case StoredObjCOneArgSelector: return ObjCOneArgSelector; - - case StoredDeclarationNameExtra: - switch (getExtra()->ExtraKindOrNumArgs) { - case DeclarationNameExtra::CXXConstructor: - return CXXConstructorName; - - case DeclarationNameExtra::CXXDestructor: - return CXXDestructorName; - - case DeclarationNameExtra::CXXDeductionGuide: - return CXXDeductionGuideName; - - case DeclarationNameExtra::CXXConversionFunction: - return CXXConversionFunctionName; - - case DeclarationNameExtra::CXXLiteralOperator: - return CXXLiteralOperatorName; - - case DeclarationNameExtra::CXXUsingDirective: - return CXXUsingDirective; - - default: - // Check if we have one of the CXXOperator* enumeration values. - if (getExtra()->ExtraKindOrNumArgs < - DeclarationNameExtra::CXXUsingDirective) - return CXXOperatorName; - - return ObjCMultiArgSelector; - } - } - - // Can't actually get here. - llvm_unreachable("This should be unreachable!"); -} - bool DeclarationName::isDependentName() const { QualType T = getCXXNameType(); if (!T.isNull() && T->isDependentType()) @@ -337,241 +233,148 @@ std::string DeclarationName::getAsString() const { return OS.str(); } -QualType DeclarationName::getCXXNameType() const { - if (CXXSpecialName *CXXName = getAsCXXSpecialName()) - return CXXName->Type; - else - return QualType(); -} - -TemplateDecl *DeclarationName::getCXXDeductionGuideTemplate() const { - if (auto *Guide = getAsCXXDeductionGuideNameExtra()) - return Guide->Template; - return nullptr; -} - -OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const { - if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) { - unsigned value - = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction; - return static_cast<OverloadedOperatorKind>(value); - } else { - return OO_None; - } -} - -IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const { - if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName()) - return CXXLit->ID; - else - return nullptr; -} - -void *DeclarationName::getFETokenInfoAsVoidSlow() const { +void *DeclarationName::getFETokenInfoSlow() const { switch (getNameKind()) { case Identifier: - llvm_unreachable("Handled by getFETokenInfo()"); - + llvm_unreachable("case Identifier already handled by getFETokenInfo!"); case CXXConstructorName: case CXXDestructorName: case CXXConversionFunctionName: - return getAsCXXSpecialName()->FETokenInfo; - - case CXXDeductionGuideName: - return getAsCXXDeductionGuideNameExtra()->FETokenInfo; - + return castAsCXXSpecialNameExtra()->FETokenInfo; case CXXOperatorName: - return getAsCXXOperatorIdName()->FETokenInfo; - + return castAsCXXOperatorIdName()->FETokenInfo; + case CXXDeductionGuideName: + return castAsCXXDeductionGuideNameExtra()->FETokenInfo; case CXXLiteralOperatorName: - return getAsCXXLiteralOperatorIdName()->FETokenInfo; - + return castAsCXXLiteralOperatorIdName()->FETokenInfo; default: - llvm_unreachable("Declaration name has no FETokenInfo"); + llvm_unreachable("DeclarationName has no FETokenInfo!"); } } -void DeclarationName::setFETokenInfo(void *T) { +void DeclarationName::setFETokenInfoSlow(void *T) { switch (getNameKind()) { case Identifier: - getAsIdentifierInfo()->setFETokenInfo(T); - break; - + llvm_unreachable("case Identifier already handled by setFETokenInfo!"); case CXXConstructorName: case CXXDestructorName: case CXXConversionFunctionName: - getAsCXXSpecialName()->FETokenInfo = T; - break; - - case CXXDeductionGuideName: - getAsCXXDeductionGuideNameExtra()->FETokenInfo = T; + castAsCXXSpecialNameExtra()->FETokenInfo = T; break; - case CXXOperatorName: - getAsCXXOperatorIdName()->FETokenInfo = T; + castAsCXXOperatorIdName()->FETokenInfo = T; + break; + case CXXDeductionGuideName: + castAsCXXDeductionGuideNameExtra()->FETokenInfo = T; break; - case CXXLiteralOperatorName: - getAsCXXLiteralOperatorIdName()->FETokenInfo = T; + castAsCXXLiteralOperatorIdName()->FETokenInfo = T; break; - default: - llvm_unreachable("Declaration name has no FETokenInfo"); + llvm_unreachable("DeclarationName has no FETokenInfo!"); } } -DeclarationName DeclarationName::getUsingDirectiveName() { - // Single instance of DeclarationNameExtra for using-directive - static const DeclarationNameExtra UDirExtra = - { DeclarationNameExtra::CXXUsingDirective }; - - uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra); - Ptr |= StoredDeclarationNameExtra; - - return DeclarationName(Ptr); -} - LLVM_DUMP_METHOD void DeclarationName::dump() const { llvm::errs() << *this << '\n'; } DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { - CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>; - CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>; - CXXDeductionGuideNames = new llvm::FoldingSet<CXXDeductionGuideNameExtra>; - // Initialize the overloaded operator names. - CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS]; - for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) { - CXXOperatorNames[Op].ExtraKindOrNumArgs - = Op + DeclarationNameExtra::CXXConversionFunction; - CXXOperatorNames[Op].FETokenInfo = nullptr; - } -} - -DeclarationNameTable::~DeclarationNameTable() { - auto *SpecialNames = - static_cast<llvm::FoldingSet<CXXSpecialName> *>(CXXSpecialNamesImpl); - auto *LiteralNames = - static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName> *>( - CXXLiteralOperatorNames); - auto *DeductionGuideNames = - static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>( - CXXDeductionGuideNames); - - delete SpecialNames; - delete LiteralNames; - delete DeductionGuideNames; -} - -DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXConstructorName, - Ty.getUnqualifiedType()); -} - -DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXDestructorName, - Ty.getUnqualifiedType()); + for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) + CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op); } DeclarationName DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) { Template = cast<TemplateDecl>(Template->getCanonicalDecl()); - auto *DeductionGuideNames = - static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>( - CXXDeductionGuideNames); - llvm::FoldingSetNodeID ID; ID.AddPointer(Template); void *InsertPos = nullptr; - if (auto *Name = DeductionGuideNames->FindNodeOrInsertPos(ID, InsertPos)) + if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos)) return DeclarationName(Name); - auto *Name = new (Ctx) CXXDeductionGuideNameExtra; - Name->ExtraKindOrNumArgs = DeclarationNameExtra::CXXDeductionGuide; - Name->Template = Template; - Name->FETokenInfo = nullptr; - - DeductionGuideNames->InsertNode(Name, InsertPos); + auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template); + CXXDeductionGuideNames.InsertNode(Name, InsertPos); return DeclarationName(Name); } +DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) { + // The type of constructors is unqualified. + Ty = Ty.getUnqualifiedType(); + // Do we already have this C++ constructor name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXConstructorName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXConstructorNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXConstructorName}; +} + +DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { + // The type of destructors is unqualified. + Ty = Ty.getUnqualifiedType(); + // Do we already have this C++ destructor name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXDestructorName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXDestructorNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXDestructorName}; +} + DeclarationName DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty); + // Do we already have this C++ conversion function name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = + CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXConversionFunctionName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXConversionFunctionName}; } DeclarationName DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, CanQualType Ty) { - assert(Kind >= DeclarationName::CXXConstructorName && - Kind <= DeclarationName::CXXConversionFunctionName && - "Kind must be a C++ special name kind"); - llvm::FoldingSet<CXXSpecialName> *SpecialNames - = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl); - - DeclarationNameExtra::ExtraKind EKind; switch (Kind) { case DeclarationName::CXXConstructorName: - EKind = DeclarationNameExtra::CXXConstructor; - assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified"); - break; + return getCXXConstructorName(Ty); case DeclarationName::CXXDestructorName: - EKind = DeclarationNameExtra::CXXDestructor; - assert(!Ty.hasQualifiers() && "Destructor type must be unqualified"); - break; + return getCXXDestructorName(Ty); case DeclarationName::CXXConversionFunctionName: - EKind = DeclarationNameExtra::CXXConversionFunction; - break; + return getCXXConversionFunctionName(Ty); default: - return DeclarationName(); + llvm_unreachable("Invalid kind in getCXXSpecialName!"); } - - // Unique selector, to guarantee there is one per name. - llvm::FoldingSetNodeID ID; - ID.AddInteger(EKind); - ID.AddPointer(Ty.getAsOpaquePtr()); - - void *InsertPos = nullptr; - if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos)) - return DeclarationName(Name); - - CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName; - SpecialName->ExtraKindOrNumArgs = EKind; - SpecialName->Type = Ty; - SpecialName->FETokenInfo = nullptr; - - SpecialNames->InsertNode(SpecialName, InsertPos); - return DeclarationName(SpecialName); -} - -DeclarationName -DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) { - return DeclarationName(&CXXOperatorNames[(unsigned)Op]); } DeclarationName DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { - llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames - = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*> - (CXXLiteralOperatorNames); - llvm::FoldingSetNodeID ID; ID.AddPointer(II); void *InsertPos = nullptr; - if (CXXLiteralOperatorIdName *Name = - LiteralNames->FindNodeOrInsertPos(ID, InsertPos)) - return DeclarationName (Name); - - CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName; - LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator; - LiteralName->ID = II; - LiteralName->FETokenInfo = nullptr; + if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos)) + return DeclarationName(Name); - LiteralNames->InsertNode(LiteralName, InsertPos); + auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II); + CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos); return DeclarationName(LiteralName); } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 7556c76c38bd..7cdd3b2c2a30 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> @@ -192,7 +191,7 @@ bool Expr::isKnownToHaveBooleanValue() const { // Amusing macro metaprogramming hack: check whether a class provides // a more specific implementation of getExprLoc(). // -// See also Stmt.cpp:{getLocStart(),getLocEnd()}. +// See also Stmt.cpp:{getBeginLoc(),getEndLoc()}. namespace { /// This implementation is used when a class provides a custom /// implementation of getExprLoc. @@ -209,7 +208,7 @@ namespace { template <class E> SourceLocation getExprLocImpl(const Expr *expr, SourceLocation (Expr::*v)() const) { - return static_cast<const E*>(expr)->getLocStart(); + return static_cast<const E *>(expr)->getBeginLoc(); } } @@ -342,16 +341,32 @@ void DeclRefExpr::computeDependence(const ASTContext &Ctx) { ExprBits.ContainsUnexpandedParameterPack = true; } +DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, + bool RefersToEnclosingVariableOrCapture, QualType T, + ExprValueKind VK, SourceLocation L, + const DeclarationNameLoc &LocInfo) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), + D(D), DNLoc(LocInfo) { + DeclRefExprBits.HasQualifier = false; + DeclRefExprBits.HasTemplateKWAndArgsInfo = false; + DeclRefExprBits.HasFoundDecl = false; + DeclRefExprBits.HadMultipleCandidates = false; + DeclRefExprBits.RefersToEnclosingVariableOrCapture = + RefersToEnclosingVariableOrCapture; + DeclRefExprBits.Loc = L; + computeDependence(Ctx); +} + DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - ValueDecl *D, bool RefersToEnclosingVariableOrCapture, - const DeclarationNameInfo &NameInfo, - NamedDecl *FoundD, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnclosingVariableOrCapture, + const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, 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()) { + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), + D(D), DNLoc(NameInfo.getInfo()) { + DeclRefExprBits.Loc = NameInfo.getLoc(); DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; if (QualifierLoc) { new (getTrailingObjects<NestedNameSpecifierLoc>()) @@ -447,31 +462,56 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context, return new (Mem) DeclRefExpr(EmptyShell()); } -SourceLocation DeclRefExpr::getLocStart() const { +SourceLocation DeclRefExpr::getBeginLoc() const { if (hasQualifier()) return getQualifierLoc().getBeginLoc(); - return getNameInfo().getLocStart(); + return getNameInfo().getBeginLoc(); } -SourceLocation DeclRefExpr::getLocEnd() const { +SourceLocation DeclRefExpr::getEndLoc() const { if (hasExplicitTemplateArgs()) return getRAngleLoc(); - return getNameInfo().getLocEnd(); + 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 +529,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 +572,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 +604,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 +629,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 +728,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 +753,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"; } @@ -785,7 +825,7 @@ std::string FixedPointLiteral::getValueAsString(unsigned Radix) const { // which is 43 characters. SmallString<64> S; FixedPointValueToString( - S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale, Radix); + S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale); return S.str(); } @@ -861,66 +901,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!"); - // 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); + // 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!"); + } - // OPTIMIZE: could allocate this appended to the StringLiteral. - SL->setString(C,Str,Kind,Pascal); + StringLiteralBits.Kind = Kind; + StringLiteralBits.CharByteWidth = CharByteWidth; + StringLiteralBits.IsPascal = Pascal; + StringLiteralBits.NumConcatenated = NumConcatenated; + *getTrailingObjects<unsigned>() = Length; - SL->TokLocs[0] = Loc[0]; - SL->NumConcatenated = NumStrs; + // Initialize the trailing array of SourceLocation. + // This is safe since SourceLocation is POD-like. + std::memcpy(getTrailingObjects<SourceLocation>(), Loc, + NumConcatenated * sizeof(SourceLocation)); - if (NumStrs != 1) - memcpy(&SL->TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1)); - return SL; + // Initialize the trailing array of char holding the string data. + std::memcpy(getTrailingObjects<char>(), Str.data(), ByteLength); } -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(EmptyShell Empty, unsigned NumConcatenated, + unsigned Length, unsigned CharByteWidth) + : Expr(StringLiteralClass, Empty) { + StringLiteralBits.CharByteWidth = CharByteWidth; + StringLiteralBits.NumConcatenated = NumConcatenated; + *getTrailingObjects<unsigned>() = Length; +} + +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 +1098,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 +1119,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 +1188,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) { @@ -1192,49 +1234,98 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { // Postfix Operators. //===----------------------------------------------------------------------===// -CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, - ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t, - ExprValueKind VK, SourceLocation rparenloc) - : Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(), - fn->isValueDependent(), fn->isInstantiationDependent(), - fn->containsUnexpandedParameterPack()), - NumArgs(args.size()) { +CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation RParenLoc, unsigned MinNumArgs, + ADLCallKind UsesADL) + : Expr(SC, Ty, VK, OK_Ordinary, Fn->isTypeDependent(), + Fn->isValueDependent(), Fn->isInstantiationDependent(), + Fn->containsUnexpandedParameterPack()), + RParenLoc(RParenLoc) { + NumArgs = std::max<unsigned>(Args.size(), MinNumArgs); + unsigned NumPreArgs = PreArgs.size(); + CallExprBits.NumPreArgs = NumPreArgs; + assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!"); + + unsigned OffsetToTrailingObjects = offsetToTrailingObjects(SC); + CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects; + assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) && + "OffsetToTrailingObjects overflow!"); + + CallExprBits.UsesADL = static_cast<bool>(UsesADL); - unsigned NumPreArgs = preargs.size(); - SubExprs = new (C) Stmt *[args.size()+PREARGS_START+NumPreArgs]; - SubExprs[FN] = fn; - for (unsigned i = 0; i != NumPreArgs; ++i) { - updateDependenciesFromArg(preargs[i]); - SubExprs[i+PREARGS_START] = preargs[i]; + setCallee(Fn); + for (unsigned I = 0; I != NumPreArgs; ++I) { + updateDependenciesFromArg(PreArgs[I]); + setPreArg(I, PreArgs[I]); } - for (unsigned i = 0; i != args.size(); ++i) { - updateDependenciesFromArg(args[i]); - SubExprs[i+PREARGS_START+NumPreArgs] = args[i]; + for (unsigned I = 0; I != Args.size(); ++I) { + updateDependenciesFromArg(Args[I]); + setArg(I, Args[I]); } + for (unsigned I = Args.size(); I != NumArgs; ++I) { + setArg(I, nullptr); + } +} +CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, + EmptyShell Empty) + : Expr(SC, Empty), NumArgs(NumArgs) { CallExprBits.NumPreArgs = NumPreArgs; - RParenLoc = rparenloc; + assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!"); + + unsigned OffsetToTrailingObjects = offsetToTrailingObjects(SC); + CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects; + assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) && + "OffsetToTrailingObjects overflow!"); } -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) {} +CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation RParenLoc, unsigned MinNumArgs, + ADLCallKind UsesADL) { + unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs); + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + void *Mem = + Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr)); + return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, 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::CreateTemporary(void *Mem, Expr *Fn, QualType Ty, + ExprValueKind VK, SourceLocation RParenLoc, + ADLCallKind UsesADL) { + assert(!(reinterpret_cast<uintptr_t>(Mem) % alignof(CallExpr)) && + "Misaligned memory in CallExpr::CreateTemporary!"); + return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty, + VK, RParenLoc, /*MinNumArgs=*/0, UsesADL); } -CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) - : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {} +CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + EmptyShell Empty) { + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + void *Mem = + Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr)); + return new (Mem) CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, Empty); +} -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](); - CallExprBits.NumPreArgs = NumPreArgs; +unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) { + switch (SC) { + case CallExprClass: + return sizeof(CallExpr); + case CXXOperatorCallExprClass: + return sizeof(CXXOperatorCallExpr); + case CXXMemberCallExprClass: + return sizeof(CXXMemberCallExpr); + case UserDefinedLiteralClass: + return sizeof(UserDefinedLiteral); + case CUDAKernelCallExprClass: + return sizeof(CUDAKernelCallExpr); + default: + llvm_unreachable("unexpected class deriving from CallExpr!"); + } } void CallExpr::updateDependenciesFromArg(Expr *Arg) { @@ -1248,14 +1339,6 @@ void CallExpr::updateDependenciesFromArg(Expr *Arg) { ExprBits.ContainsUnexpandedParameterPack = true; } -FunctionDecl *CallExpr::getDirectCallee() { - return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); -} - -Decl *CallExpr::getCalleeDecl() { - return getCallee()->getReferencedDeclOfCallee(); -} - Decl *Expr::getReferencedDeclOfCallee() { Expr *CEE = IgnoreParenImpCasts(); @@ -1280,35 +1363,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 { @@ -1358,22 +1412,35 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { return FnType->getReturnType(); } -SourceLocation CallExpr::getLocStart() const { +const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { + // If the return type is a struct, union, or enum that is marked nodiscard, + // then return the return type attribute. + if (const TagDecl *TD = getCallReturnType(Ctx)->getAsTagDecl()) + if (const auto *A = TD->getAttr<WarnUnusedResultAttr>()) + return A; + + // Otherwise, see if the callee is marked nodiscard and return that attribute + // instead. + const Decl *D = getCalleeDecl(); + return D ? D->getAttr<WarnUnusedResultAttr>() : nullptr; +} + +SourceLocation CallExpr::getBeginLoc() const { if (isa<CXXOperatorCallExpr>(this)) - return cast<CXXOperatorCallExpr>(this)->getLocStart(); + return cast<CXXOperatorCallExpr>(this)->getBeginLoc(); - SourceLocation begin = getCallee()->getLocStart(); + SourceLocation begin = getCallee()->getBeginLoc(); if (begin.isInvalid() && getNumArgs() > 0 && getArg(0)) - begin = getArg(0)->getLocStart(); + begin = getArg(0)->getBeginLoc(); return begin; } -SourceLocation CallExpr::getLocEnd() const { +SourceLocation CallExpr::getEndLoc() const { if (isa<CXXOperatorCallExpr>(this)) - return cast<CXXOperatorCallExpr>(this)->getLocEnd(); + return cast<CXXOperatorCallExpr>(this)->getEndLoc(); SourceLocation end = getRParenLoc(); if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1)) - end = getArg(getNumArgs() - 1)->getLocEnd(); + end = getArg(getNumArgs() - 1)->getEndLoc(); return end; } @@ -1446,7 +1513,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 +1569,7 @@ MemberExpr *MemberExpr::Create( QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) E->setInstantiationDependent(true); - E->HasQualifierOrFoundDecl = true; + E->MemberExprBits.HasQualifierOrFoundDecl = true; MemberExprNameQualifier *NQ = E->getTrailingObjects<MemberExprNameQualifier>(); @@ -1510,7 +1577,8 @@ MemberExpr *MemberExpr::Create( NQ->FoundDecl = founddecl; } - E->HasTemplateKWAndArgsInfo = (targs || TemplateKWLoc.isValid()); + E->MemberExprBits.HasTemplateKWAndArgsInfo = + (targs || TemplateKWLoc.isValid()); if (targs) { bool Dependent = false; @@ -1529,7 +1597,7 @@ MemberExpr *MemberExpr::Create( return E; } -SourceLocation MemberExpr::getLocStart() const { +SourceLocation MemberExpr::getBeginLoc() const { if (isImplicitAccess()) { if (hasQualifier()) return getQualifierLoc().getBeginLoc(); @@ -1538,17 +1606,17 @@ SourceLocation MemberExpr::getLocStart() const { // FIXME: We don't want this to happen. Rather, we should be able to // detect all kinds of implicit accesses more cleanly. - SourceLocation BaseStartLoc = getBase()->getLocStart(); + SourceLocation BaseStartLoc = getBase()->getBeginLoc(); if (BaseStartLoc.isValid()) return BaseStartLoc; return MemberLoc; } -SourceLocation MemberExpr::getLocEnd() const { +SourceLocation MemberExpr::getEndLoc() const { SourceLocation EndLoc = getMemberNameInfo().getEndLoc(); if (hasExplicitTemplateArgs()) EndLoc = getRAngleLoc(); else if (EndLoc.isInvalid()) - EndLoc = getBase()->getLocEnd(); + EndLoc = getBase()->getEndLoc(); return EndLoc; } @@ -1605,13 +1673,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 (isRValue()) { + Ty = Ty->getPointeeType(); + 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 +1714,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 +1734,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; @@ -1734,21 +1808,6 @@ NamedDecl *CastExpr::getConversionFunction() const { return nullptr; } -CastExpr::BasePathSizeTy *CastExpr::BasePathSize() { - assert(!path_empty()); - switch (getStmtClass()) { -#define ABSTRACT_STMT(x) -#define CASTEXPR(Type, Base) \ - case Stmt::Type##Class: \ - return static_cast<Type *>(this) \ - ->getTrailingObjects<CastExpr::BasePathSizeTy>(); -#define STMT(Type, Base) -#include "clang/AST/StmtNodes.inc" - default: - llvm_unreachable("non-cast expressions not possible here"); - } -} - CXXBaseSpecifier **CastExpr::path_buffer() { switch (getStmtClass()) { #define ABSTRACT_STMT(x) @@ -1787,9 +1846,7 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T, const CXXCastPath *BasePath, ExprValueKind VK) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); ImplicitCastExpr *E = new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK); if (PathSize) @@ -1800,9 +1857,7 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T, ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize); } @@ -1813,9 +1868,7 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); CStyleCastExpr *E = new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R); if (PathSize) @@ -1826,9 +1879,7 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T, CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize); } @@ -2039,9 +2090,9 @@ bool InitListExpr::isIdiomaticZeroInitializer(const LangOptions &LangOpts) const return Lit && Lit->getValue() == 0; } -SourceLocation InitListExpr::getLocStart() const { +SourceLocation InitListExpr::getBeginLoc() const { if (InitListExpr *SyntacticForm = getSyntacticForm()) - return SyntacticForm->getLocStart(); + return SyntacticForm->getBeginLoc(); SourceLocation Beg = LBraceLoc; if (Beg.isInvalid()) { // Find the first non-null initializer. @@ -2049,7 +2100,7 @@ SourceLocation InitListExpr::getLocStart() const { E = InitExprs.end(); I != E; ++I) { if (Stmt *S = *I) { - Beg = S->getLocStart(); + Beg = S->getBeginLoc(); break; } } @@ -2057,9 +2108,9 @@ SourceLocation InitListExpr::getLocStart() const { return Beg; } -SourceLocation InitListExpr::getLocEnd() const { +SourceLocation InitListExpr::getEndLoc() const { if (InitListExpr *SyntacticForm = getSyntacticForm()) - return SyntacticForm->getLocEnd(); + return SyntacticForm->getEndLoc(); SourceLocation End = RBraceLoc; if (End.isInvalid()) { // Find the first non-null initializer from the end. @@ -2067,7 +2118,7 @@ SourceLocation InitListExpr::getLocEnd() const { E = InitExprs.rend(); I != E; ++I) { if (Stmt *S = *I) { - End = S->getLocEnd(); + End = S->getEndLoc(); break; } } @@ -2262,24 +2313,20 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // If this is a direct call, get the callee. const CallExpr *CE = cast<CallExpr>(this); if (const Decl *FD = CE->getCalleeDecl()) { - const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD); - bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr() - : FD->hasAttr<WarnUnusedResultAttr>(); - // If the callee has attribute pure, const, or warn_unused_result, warn // about it. void foo() { strlen("bar"); } should warn. // // Note: If new cases are added here, DiagnoseUnusedExprResult should be // updated to match for QoI. - if (HasWarnUnusedResultAttr || + if (CE->hasUnusedResultAttr(Ctx) || FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) { WarnE = this; - Loc = CE->getCallee()->getLocStart(); + Loc = CE->getCallee()->getBeginLoc(); R1 = CE->getCallee()->getSourceRange(); if (unsigned NumArgs = CE->getNumArgs()) - R2 = SourceRange(CE->getArg(0)->getLocStart(), - CE->getArg(NumArgs-1)->getLocEnd()); + R2 = SourceRange(CE->getArg(0)->getBeginLoc(), + CE->getArg(NumArgs - 1)->getEndLoc()); return true; } } @@ -2296,7 +2343,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) { if (Type->hasAttr<WarnUnusedAttr>()) { WarnE = this; - Loc = getLocStart(); + Loc = getBeginLoc(); R1 = getSourceRange(); return true; } @@ -2396,7 +2443,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, WarnE = this; if (const CXXFunctionalCastExpr *CXXCE = dyn_cast<CXXFunctionalCastExpr>(this)) { - Loc = CXXCE->getLocStart(); + Loc = CXXCE->getBeginLoc(); R1 = CXXCE->getSubExpr()->getSourceRange(); } else { const CStyleCastExpr *CStyleCE = cast<CStyleCastExpr>(this); @@ -2535,6 +2582,10 @@ Expr* Expr::IgnoreParens() { continue; } } + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) { + E = CE->getSubExpr(); + continue; + } return E; } } @@ -2559,6 +2610,10 @@ Expr *Expr::IgnoreParenCasts() { E = NTTP->getReplacement(); continue; } + if (FullExpr *FE = dyn_cast<FullExpr>(E)) { + E = FE->getSubExpr(); + continue; + } return E; } } @@ -2580,6 +2635,10 @@ Expr *Expr::IgnoreCasts() { E = NTTP->getReplacement(); continue; } + if (FullExpr *FE = dyn_cast<FullExpr>(E)) { + E = FE->getSubExpr(); + continue; + } return E; } } @@ -2605,6 +2664,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; } @@ -2870,6 +2932,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 +2977,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 +3163,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 +3327,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 +3459,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); } } @@ -3866,11 +3936,11 @@ SourceRange DesignatedInitExpr::getDesignatorsSourceRange() const { DesignatedInitExpr *DIE = const_cast<DesignatedInitExpr*>(this); if (size() == 1) return DIE->getDesignator(0)->getSourceRange(); - return SourceRange(DIE->getDesignator(0)->getLocStart(), - DIE->getDesignator(size()-1)->getLocEnd()); + return SourceRange(DIE->getDesignator(0)->getBeginLoc(), + DIE->getDesignator(size() - 1)->getEndLoc()); } -SourceLocation DesignatedInitExpr::getLocStart() const { +SourceLocation DesignatedInitExpr::getBeginLoc() const { SourceLocation StartLoc; auto *DIE = const_cast<DesignatedInitExpr *>(this); Designator &First = *DIE->getDesignator(0); @@ -3885,8 +3955,8 @@ SourceLocation DesignatedInitExpr::getLocStart() const { return StartLoc; } -SourceLocation DesignatedInitExpr::getLocEnd() const { - return getInit()->getLocEnd(); +SourceLocation DesignatedInitExpr::getEndLoc() const { + return getInit()->getEndLoc(); } Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) const { @@ -3944,35 +4014,56 @@ DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C, BaseAndUpdaterExprs[1] = ILE; } -SourceLocation DesignatedInitUpdateExpr::getLocStart() const { - return getBase()->getLocStart(); +SourceLocation DesignatedInitUpdateExpr::getBeginLoc() const { + return getBase()->getBeginLoc(); } -SourceLocation DesignatedInitUpdateExpr::getLocEnd() const { - return getBase()->getLocEnd(); +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 93d68ec8e0b2..3891f45c7fc2 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -89,88 +89,132 @@ QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const { } // CXXScalarValueInitExpr -SourceLocation CXXScalarValueInitExpr::getLocStart() const { - return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : RParenLoc; +SourceLocation CXXScalarValueInitExpr::getBeginLoc() const { + return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : getRParenLoc(); } // CXXNewExpr -CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, - FunctionDecl *operatorNew, FunctionDecl *operatorDelete, - bool PassAlignment, bool usualArrayDeleteWantsSize, - ArrayRef<Expr*> placementArgs, - SourceRange typeIdParens, Expr *arraySize, - InitializationStyle initializationStyle, - Expr *initializer, QualType ty, - TypeSourceInfo *allocatedTypeInfo, - SourceRange Range, SourceRange directInitRange) - : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, ty->isDependentType(), - ty->isDependentType(), ty->isInstantiationDependentType(), - ty->containsUnexpandedParameterPack()), - OperatorNew(operatorNew), OperatorDelete(operatorDelete), - AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), - Range(Range), DirectInitRange(directInitRange), GlobalNew(globalNew), - PassAlignment(PassAlignment), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { - assert((initializer != nullptr || initializationStyle == NoInit) && - "Only NoInit can have no initializer."); - StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; - AllocateArgsArray(C, arraySize != nullptr, placementArgs.size(), - initializer != nullptr); - unsigned i = 0; - if (Array) { - if (arraySize->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; +CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, + ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens, + Expr *ArraySize, InitializationStyle InitializationStyle, + Expr *Initializer, QualType Ty, + TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange) + : Expr(CXXNewExprClass, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(), + Ty->isDependentType(), Ty->isInstantiationDependentType(), + Ty->containsUnexpandedParameterPack()), + OperatorNew(OperatorNew), OperatorDelete(OperatorDelete), + AllocatedTypeInfo(AllocatedTypeInfo), Range(Range), + DirectInitRange(DirectInitRange) { + + assert((Initializer != nullptr || InitializationStyle == NoInit) && + "Only NoInit can have no initializer!"); + + CXXNewExprBits.IsGlobalNew = IsGlobalNew; + CXXNewExprBits.IsArray = ArraySize != nullptr; + CXXNewExprBits.ShouldPassAlignment = ShouldPassAlignment; + CXXNewExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; + CXXNewExprBits.StoredInitializationStyle = + Initializer ? InitializationStyle + 1 : 0; + bool IsParenTypeId = TypeIdParens.isValid(); + CXXNewExprBits.IsParenTypeId = IsParenTypeId; + CXXNewExprBits.NumPlacementArgs = PlacementArgs.size(); - if (arraySize->containsUnexpandedParameterPack()) + if (ArraySize) { + if (ArraySize->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (ArraySize->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = arraySize; + getTrailingObjects<Stmt *>()[arraySizeOffset()] = ArraySize; } - if (initializer) { - if (initializer->isInstantiationDependent()) + if (Initializer) { + if (Initializer->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - - if (initializer->containsUnexpandedParameterPack()) + if (Initializer->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = initializer; + getTrailingObjects<Stmt *>()[initExprOffset()] = Initializer; } - for (unsigned j = 0; j != placementArgs.size(); ++j) { - if (placementArgs[j]->isInstantiationDependent()) + for (unsigned I = 0; I != PlacementArgs.size(); ++I) { + if (PlacementArgs[I]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (placementArgs[j]->containsUnexpandedParameterPack()) + if (PlacementArgs[I]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = placementArgs[j]; + getTrailingObjects<Stmt *>()[placementNewArgsOffset() + I] = + PlacementArgs[I]; } + if (IsParenTypeId) + getTrailingObjects<SourceRange>()[0] = TypeIdParens; + switch (getInitializationStyle()) { case CallInit: - this->Range.setEnd(DirectInitRange.getEnd()); break; + this->Range.setEnd(DirectInitRange.getEnd()); + break; case ListInit: - this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); break; + this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); + break; default: - if (TypeIdParens.isValid()) + if (IsParenTypeId) this->Range.setEnd(TypeIdParens.getEnd()); break; } } -void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray, - unsigned numPlaceArgs, bool hasInitializer){ - assert(SubExprs == nullptr && "SubExprs already allocated"); - Array = isArray; - NumPlacementArgs = numPlaceArgs; +CXXNewExpr::CXXNewExpr(EmptyShell Empty, bool IsArray, + unsigned NumPlacementArgs, bool IsParenTypeId) + : Expr(CXXNewExprClass, Empty) { + CXXNewExprBits.IsArray = IsArray; + CXXNewExprBits.NumPlacementArgs = NumPlacementArgs; + CXXNewExprBits.IsParenTypeId = IsParenTypeId; +} - unsigned TotalSize = Array + hasInitializer + NumPlacementArgs; - SubExprs = new (C) Stmt*[TotalSize]; +CXXNewExpr * +CXXNewExpr::Create(const ASTContext &Ctx, bool IsGlobalNew, + FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete, + bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, + ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens, + Expr *ArraySize, InitializationStyle InitializationStyle, + Expr *Initializer, QualType Ty, + TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange) { + bool IsArray = ArraySize != nullptr; + bool HasInit = Initializer != nullptr; + unsigned NumPlacementArgs = PlacementArgs.size(); + bool IsParenTypeId = TypeIdParens.isValid(); + void *Mem = + Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>( + IsArray + HasInit + NumPlacementArgs, IsParenTypeId), + alignof(CXXNewExpr)); + return new (Mem) + CXXNewExpr(IsGlobalNew, OperatorNew, OperatorDelete, ShouldPassAlignment, + UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens, + ArraySize, InitializationStyle, Initializer, Ty, + AllocatedTypeInfo, Range, DirectInitRange); +} + +CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray, + bool HasInit, unsigned NumPlacementArgs, + bool IsParenTypeId) { + void *Mem = + Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>( + IsArray + HasInit + NumPlacementArgs, IsParenTypeId), + alignof(CXXNewExpr)); + return new (Mem) + CXXNewExpr(EmptyShell(), IsArray, NumPlacementArgs, IsParenTypeId); } -bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const { - return getOperatorNew()->getType()->castAs<FunctionProtoType>() - ->isNothrow() && +bool CXXNewExpr::shouldNullCheckAllocation() const { + return getOperatorNew() + ->getType() + ->castAs<FunctionProtoType>() + ->isNothrow() && !getOperatorNew()->isReservedGlobalPlacementOperator(); } @@ -250,7 +294,7 @@ QualType CXXPseudoDestructorExpr::getDestroyedType() const { return QualType(); } -SourceLocation CXXPseudoDestructorExpr::getLocEnd() const { +SourceLocation CXXPseudoDestructorExpr::getEndLoc() const { SourceLocation End = DestroyedType.getLocation(); if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo()) End = TInfo->getTypeLoc().getLocalSourceRange().getEnd(); @@ -258,68 +302,95 @@ SourceLocation CXXPseudoDestructorExpr::getLocEnd() const { } // UnresolvedLookupExpr -UnresolvedLookupExpr * -UnresolvedLookupExpr::Create(const ASTContext &C, - CXXRecordDecl *NamingClass, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - bool ADL, - const TemplateArgumentListInfo *Args, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - assert(Args || TemplateKWLoc.isValid()); - unsigned num_args = Args ? Args->size() : 0; +UnresolvedLookupExpr::UnresolvedLookupExpr( + const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, + const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, + UnresolvedSetIterator End) + : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, + TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, false, + false, false), + NamingClass(NamingClass) { + UnresolvedLookupExprBits.RequiresADL = RequiresADL; + UnresolvedLookupExprBits.Overloaded = Overloaded; +} - std::size_t Size = - totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1, - num_args); - void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr)); - return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, - TemplateKWLoc, NameInfo, - ADL, /*Overload*/ true, Args, - Begin, End); +UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty, + unsigned NumResults, + bool HasTemplateKWAndArgsInfo) + : OverloadExpr(UnresolvedLookupExprClass, Empty, NumResults, + HasTemplateKWAndArgsInfo) {} + +UnresolvedLookupExpr *UnresolvedLookupExpr::Create( + const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, + bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + unsigned NumResults = End - Begin; + unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc>(NumResults, 0, 0); + void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); + return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, + SourceLocation(), NameInfo, RequiresADL, + Overloaded, nullptr, Begin, End); +} + +UnresolvedLookupExpr *UnresolvedLookupExpr::Create( + const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, + const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + assert(Args || TemplateKWLoc.isValid()); + unsigned NumResults = End - Begin; + unsigned NumTemplateArgs = Args ? Args->size() : 0; + unsigned Size = + totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc>(NumResults, 1, NumTemplateArgs); + void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); + return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, + TemplateKWLoc, NameInfo, RequiresADL, + /*Overloaded*/ true, Args, Begin, End); } -UnresolvedLookupExpr * -UnresolvedLookupExpr::CreateEmpty(const ASTContext &C, - bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs) { +UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty( + const ASTContext &Context, unsigned NumResults, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); - std::size_t Size = - totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( - HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr)); - auto *E = new (Mem) UnresolvedLookupExpr(EmptyShell()); - E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; - return E; + unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc>( + NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs); + void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); + return new (Mem) + UnresolvedLookupExpr(EmptyShell(), NumResults, HasTemplateKWAndArgsInfo); } -OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, +OverloadExpr::OverloadExpr(StmtClass SC, const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, - bool KnownDependent, + UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent, bool KnownContainsUnexpandedParameterPack) - : Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent, - KnownDependent, - (KnownInstantiationDependent || - NameInfo.isInstantiationDependent() || - (QualifierLoc && + : Expr( + SC, Context.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent, + KnownDependent, + (KnownInstantiationDependent || NameInfo.isInstantiationDependent() || + (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())), - (KnownContainsUnexpandedParameterPack || - NameInfo.containsUnexpandedParameterPack() || - (QualifierLoc && - QualifierLoc.getNestedNameSpecifier() - ->containsUnexpandedParameterPack()))), - NameInfo(NameInfo), QualifierLoc(QualifierLoc), NumResults(End - Begin), - HasTemplateKWAndArgsInfo(TemplateArgs != nullptr || - TemplateKWLoc.isValid()) { - NumResults = End - Begin; + (KnownContainsUnexpandedParameterPack || + NameInfo.containsUnexpandedParameterPack() || + (QualifierLoc && QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()))), + NameInfo(NameInfo), QualifierLoc(QualifierLoc) { + unsigned NumResults = End - Begin; + OverloadExprBits.NumResults = NumResults; + OverloadExprBits.HasTemplateKWAndArgsInfo = + (TemplateArgs != nullptr ) || TemplateKWLoc.isValid(); + if (NumResults) { // Determine whether this expression is type-dependent. for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I) { @@ -331,8 +402,9 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, } } - Results = static_cast<DeclAccessPair *>(C.Allocate( - sizeof(DeclAccessPair) * NumResults, alignof(DeclAccessPair))); + // Copy the results to the trailing array past UnresolvedLookupExpr + // or UnresolvedMemberExpr. + DeclAccessPair *Results = getTrailingResults(); memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); } @@ -360,48 +432,33 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, } if (isTypeDependent()) - setType(C.DependentTy); -} - -void OverloadExpr::initializeResults(const ASTContext &C, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - assert(!Results && "Results already initialized!"); - NumResults = End - Begin; - if (NumResults) { - Results = static_cast<DeclAccessPair *>( - C.Allocate(sizeof(DeclAccessPair) * NumResults, - - alignof(DeclAccessPair))); - memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair)); - } + setType(Context.DependentTy); } -CXXRecordDecl *OverloadExpr::getNamingClass() const { - if (isa<UnresolvedLookupExpr>(this)) - return cast<UnresolvedLookupExpr>(this)->getNamingClass(); - else - return cast<UnresolvedMemberExpr>(this)->getNamingClass(); +OverloadExpr::OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo) + : Expr(SC, Empty) { + OverloadExprBits.NumResults = NumResults; + OverloadExprBits.HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; } // DependentScopeDeclRefExpr -DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *Args) - : Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary, - true, true, - (NameInfo.isInstantiationDependent() || - (QualifierLoc && - QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())), - (NameInfo.containsUnexpandedParameterPack() || - (QualifierLoc && - QualifierLoc.getNestedNameSpecifier() - ->containsUnexpandedParameterPack()))), - QualifierLoc(QualifierLoc), NameInfo(NameInfo), - HasTemplateKWAndArgsInfo(Args != nullptr || TemplateKWLoc.isValid()) -{ +DependentScopeDeclRefExpr::DependentScopeDeclRefExpr( + QualType Ty, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *Args) + : Expr( + DependentScopeDeclRefExprClass, Ty, VK_LValue, OK_Ordinary, true, + true, + (NameInfo.isInstantiationDependent() || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())), + (NameInfo.containsUnexpandedParameterPack() || + (QualifierLoc && QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()))), + QualifierLoc(QualifierLoc), NameInfo(NameInfo) { + DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo = + (Args != nullptr) || TemplateKWLoc.isValid(); if (Args) { bool Dependent = true; bool InstantiationDependent = true; @@ -417,57 +474,55 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, } } -DependentScopeDeclRefExpr * -DependentScopeDeclRefExpr::Create(const ASTContext &C, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *Args) { +DependentScopeDeclRefExpr *DependentScopeDeclRefExpr::Create( + const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *Args) { assert(QualifierLoc && "should be created for dependent qualifiers"); bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid(); std::size_t Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, Args ? Args->size() : 0); - void *Mem = C.Allocate(Size); - return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc, + void *Mem = Context.Allocate(Size); + return new (Mem) DependentScopeDeclRefExpr(Context.DependentTy, QualifierLoc, TemplateKWLoc, NameInfo, Args); } DependentScopeDeclRefExpr * -DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C, +DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &Context, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); std::size_t Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size); - auto *E = - new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(), - SourceLocation(), - DeclarationNameInfo(), nullptr); - E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; + void *Mem = Context.Allocate(Size); + auto *E = new (Mem) DependentScopeDeclRefExpr( + QualType(), NestedNameSpecifierLoc(), SourceLocation(), + DeclarationNameInfo(), nullptr); + E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo = + HasTemplateKWAndArgsInfo; return E; } -SourceLocation CXXConstructExpr::getLocStart() const { +SourceLocation CXXConstructExpr::getBeginLoc() const { if (isa<CXXTemporaryObjectExpr>(this)) - return cast<CXXTemporaryObjectExpr>(this)->getLocStart(); - return Loc; + return cast<CXXTemporaryObjectExpr>(this)->getBeginLoc(); + return getLocation(); } -SourceLocation CXXConstructExpr::getLocEnd() const { +SourceLocation CXXConstructExpr::getEndLoc() const { if (isa<CXXTemporaryObjectExpr>(this)) - return cast<CXXTemporaryObjectExpr>(this)->getLocEnd(); + return cast<CXXTemporaryObjectExpr>(this)->getEndLoc(); if (ParenOrBraceRange.isValid()) return ParenOrBraceRange.getEnd(); - SourceLocation End = Loc; + SourceLocation End = getLocation(); for (unsigned I = getNumArgs(); I > 0; --I) { const Expr *Arg = getArg(I-1); if (!Arg->isDefaultArgument()) { - SourceLocation NewEnd = Arg->getLocEnd(); + SourceLocation NewEnd = Arg->getEndLoc(); if (NewEnd.isValid()) { End = NewEnd; break; @@ -478,30 +533,110 @@ SourceLocation CXXConstructExpr::getLocEnd() const { return End; } +CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind, + Expr *Fn, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, + SourceLocation OperatorLoc, + FPOptions FPFeatures, + ADLCallKind UsesADL) + : CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, + OperatorLoc, /*MinNumArgs=*/0, UsesADL) { + CXXOperatorCallExprBits.OperatorKind = OpKind; + CXXOperatorCallExprBits.FPFeatures = FPFeatures.getInt(); + assert( + (CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) && + "OperatorKind overflow!"); + assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) && + "FPFeatures overflow!"); + Range = getSourceRangeImpl(); +} + +CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty) + : CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {} + +CXXOperatorCallExpr *CXXOperatorCallExpr::Create( + const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL) { + // Allocate storage for the trailing objects of CallExpr. + unsigned NumArgs = Args.size(); + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects, + alignof(CXXOperatorCallExpr)); + return new (Mem) CXXOperatorCallExpr(OpKind, Fn, Args, Ty, VK, OperatorLoc, + FPFeatures, UsesADL); +} + +CXXOperatorCallExpr *CXXOperatorCallExpr::CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, + EmptyShell Empty) { + // Allocate storage for the trailing objects of CallExpr. + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects, + alignof(CXXOperatorCallExpr)); + return new (Mem) CXXOperatorCallExpr(NumArgs, Empty); +} + SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const { OverloadedOperatorKind Kind = getOperator(); if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) { if (getNumArgs() == 1) // Prefix operator - return SourceRange(getOperatorLoc(), getArg(0)->getLocEnd()); + return SourceRange(getOperatorLoc(), getArg(0)->getEndLoc()); else // Postfix operator - return SourceRange(getArg(0)->getLocStart(), getOperatorLoc()); + return SourceRange(getArg(0)->getBeginLoc(), getOperatorLoc()); } else if (Kind == OO_Arrow) { return getArg(0)->getSourceRange(); } else if (Kind == OO_Call) { - return SourceRange(getArg(0)->getLocStart(), getRParenLoc()); + return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc()); } else if (Kind == OO_Subscript) { - return SourceRange(getArg(0)->getLocStart(), getRParenLoc()); + return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc()); } else if (getNumArgs() == 1) { - return SourceRange(getOperatorLoc(), getArg(0)->getLocEnd()); + return SourceRange(getOperatorLoc(), getArg(0)->getEndLoc()); } else if (getNumArgs() == 2) { - return SourceRange(getArg(0)->getLocStart(), getArg(1)->getLocEnd()); + return SourceRange(getArg(0)->getBeginLoc(), getArg(1)->getEndLoc()); } else { return getOperatorLoc(); } } +CXXMemberCallExpr::CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, + SourceLocation RP, unsigned MinNumArgs) + : CallExpr(CXXMemberCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, RP, + MinNumArgs, NotADL) {} + +CXXMemberCallExpr::CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty) + : CallExpr(CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {} + +CXXMemberCallExpr *CXXMemberCallExpr::Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, + SourceLocation RP, + unsigned MinNumArgs) { + // Allocate storage for the trailing objects of CallExpr. + unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs); + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects, + alignof(CXXMemberCallExpr)); + return new (Mem) CXXMemberCallExpr(Fn, Args, Ty, VK, RP, MinNumArgs); +} + +CXXMemberCallExpr *CXXMemberCallExpr::CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, + EmptyShell Empty) { + // Allocate storage for the trailing objects of CallExpr. + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects, + alignof(CXXMemberCallExpr)); + return new (Mem) CXXMemberCallExpr(NumArgs, Empty); +} + Expr *CXXMemberCallExpr::getImplicitObjectArgument() const { const Expr *Callee = getCallee()->IgnoreParens(); if (const auto *MemExpr = dyn_cast<MemberExpr>(Callee)) @@ -559,9 +694,7 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T, SourceLocation RParenLoc, SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); auto *E = new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, RParenLoc, AngleBrackets); @@ -573,9 +706,7 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T, CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize); } @@ -588,9 +719,7 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T, SourceLocation RParenLoc, SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); auto *E = new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, RParenLoc, AngleBrackets); @@ -602,9 +731,7 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T, CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize); } @@ -649,9 +776,7 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T, SourceLocation RParenLoc, SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); auto *E = new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, RParenLoc, AngleBrackets); @@ -663,9 +788,7 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T, CXXReinterpretCastExpr * CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize); } @@ -688,9 +811,7 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, const CXXCastPath *BasePath, SourceLocation L, SourceLocation R) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); auto *E = new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R); if (PathSize) @@ -701,18 +822,52 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, CXXFunctionalCastExpr * CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>( - PathSize ? 1 : 0, PathSize)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize); } -SourceLocation CXXFunctionalCastExpr::getLocStart() const { - return getTypeInfoAsWritten()->getTypeLoc().getLocStart(); +SourceLocation CXXFunctionalCastExpr::getBeginLoc() const { + return getTypeInfoAsWritten()->getTypeLoc().getBeginLoc(); +} + +SourceLocation CXXFunctionalCastExpr::getEndLoc() const { + return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getEndLoc(); +} + +UserDefinedLiteral::UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, + SourceLocation LitEndLoc, + SourceLocation SuffixLoc) + : CallExpr(UserDefinedLiteralClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, + LitEndLoc, /*MinNumArgs=*/0, NotADL), + UDSuffixLoc(SuffixLoc) {} + +UserDefinedLiteral::UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty) + : CallExpr(UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs, Empty) {} + +UserDefinedLiteral *UserDefinedLiteral::Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, + SourceLocation LitEndLoc, + SourceLocation SuffixLoc) { + // Allocate storage for the trailing objects of CallExpr. + unsigned NumArgs = Args.size(); + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects, + alignof(UserDefinedLiteral)); + return new (Mem) UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc); } -SourceLocation CXXFunctionalCastExpr::getLocEnd() const { - return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getLocEnd(); +UserDefinedLiteral *UserDefinedLiteral::CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, + EmptyShell Empty) { + // Allocate storage for the trailing objects of CallExpr. + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects, + alignof(UserDefinedLiteral)); + return new (Mem) UserDefinedLiteral(NumArgs, Empty); } UserDefinedLiteral::LiteralOperatorKind @@ -749,14 +904,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()); } @@ -775,92 +931,118 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C, return new (C) CXXBindTemporaryExpr(Temp, SubExpr); } -CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C, - CXXConstructorDecl *Cons, - QualType Type, - TypeSourceInfo *TSI, - ArrayRef<Expr*> Args, - SourceRange ParenOrBraceRange, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization) - : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type, - TSI->getTypeLoc().getBeginLoc(), Cons, false, Args, - HadMultipleCandidates, ListInitialization, - StdInitListInitialization, ZeroInitialization, - CXXConstructExpr::CK_Complete, ParenOrBraceRange), - Type(TSI) {} +CXXTemporaryObjectExpr::CXXTemporaryObjectExpr( + CXXConstructorDecl *Cons, QualType Ty, TypeSourceInfo *TSI, + ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange, + bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization) + : CXXConstructExpr( + CXXTemporaryObjectExprClass, Ty, TSI->getTypeLoc().getBeginLoc(), + Cons, /* Elidable=*/false, Args, HadMultipleCandidates, + ListInitialization, StdInitListInitialization, ZeroInitialization, + CXXConstructExpr::CK_Complete, ParenOrBraceRange), + TSI(TSI) {} -SourceLocation CXXTemporaryObjectExpr::getLocStart() const { - return Type->getTypeLoc().getBeginLoc(); +CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(EmptyShell Empty, + unsigned NumArgs) + : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty, NumArgs) {} + +CXXTemporaryObjectExpr *CXXTemporaryObjectExpr::Create( + const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty, + TypeSourceInfo *TSI, ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange, + bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization) { + unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(Args.size()); + void *Mem = + Ctx.Allocate(sizeof(CXXTemporaryObjectExpr) + SizeOfTrailingObjects, + alignof(CXXTemporaryObjectExpr)); + return new (Mem) CXXTemporaryObjectExpr( + Cons, Ty, TSI, Args, ParenOrBraceRange, HadMultipleCandidates, + ListInitialization, StdInitListInitialization, ZeroInitialization); } -SourceLocation CXXTemporaryObjectExpr::getLocEnd() const { +CXXTemporaryObjectExpr * +CXXTemporaryObjectExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs) { + unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(NumArgs); + void *Mem = + Ctx.Allocate(sizeof(CXXTemporaryObjectExpr) + SizeOfTrailingObjects, + alignof(CXXTemporaryObjectExpr)); + return new (Mem) CXXTemporaryObjectExpr(EmptyShell(), NumArgs); +} + +SourceLocation CXXTemporaryObjectExpr::getBeginLoc() const { + return getTypeSourceInfo()->getTypeLoc().getBeginLoc(); +} + +SourceLocation CXXTemporaryObjectExpr::getEndLoc() const { SourceLocation Loc = getParenOrBraceRange().getEnd(); if (Loc.isInvalid() && getNumArgs()) - Loc = getArg(getNumArgs()-1)->getLocEnd(); + Loc = getArg(getNumArgs() - 1)->getEndLoc(); return Loc; } -CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, - SourceLocation Loc, - CXXConstructorDecl *Ctor, - bool Elidable, - ArrayRef<Expr*> Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, - SourceRange ParenOrBraceRange) { - return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, - Ctor, Elidable, Args, - HadMultipleCandidates, ListInitialization, - StdInitListInitialization, - ZeroInitialization, ConstructKind, - ParenOrBraceRange); +CXXConstructExpr *CXXConstructExpr::Create( + const ASTContext &Ctx, QualType Ty, SourceLocation Loc, + CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args, + bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, + ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) { + unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(Args.size()); + void *Mem = Ctx.Allocate(sizeof(CXXConstructExpr) + SizeOfTrailingObjects, + alignof(CXXConstructExpr)); + return new (Mem) CXXConstructExpr( + CXXConstructExprClass, Ty, Loc, Ctor, Elidable, Args, + HadMultipleCandidates, ListInitialization, StdInitListInitialization, + ZeroInitialization, ConstructKind, ParenOrBraceRange); } -CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, - QualType T, SourceLocation Loc, - CXXConstructorDecl *Ctor, - bool Elidable, - ArrayRef<Expr*> Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, - SourceRange ParenOrBraceRange) - : Expr(SC, T, VK_RValue, OK_Ordinary, - T->isDependentType(), T->isDependentType(), - T->isInstantiationDependentType(), - T->containsUnexpandedParameterPack()), - Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), - NumArgs(Args.size()), Elidable(Elidable), - HadMultipleCandidates(HadMultipleCandidates), - ListInitialization(ListInitialization), - StdInitListInitialization(StdInitListInitialization), - ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind) { - if (NumArgs) { - this->Args = new (C) Stmt*[Args.size()]; +CXXConstructExpr *CXXConstructExpr::CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs) { + unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(NumArgs); + void *Mem = Ctx.Allocate(sizeof(CXXConstructExpr) + SizeOfTrailingObjects, + alignof(CXXConstructExpr)); + return new (Mem) + CXXConstructExpr(CXXConstructExprClass, EmptyShell(), NumArgs); +} - for (unsigned i = 0; i != Args.size(); ++i) { - assert(Args[i] && "NULL argument in CXXConstructExpr"); +CXXConstructExpr::CXXConstructExpr( + StmtClass SC, QualType Ty, SourceLocation Loc, CXXConstructorDecl *Ctor, + bool Elidable, ArrayRef<Expr *> Args, bool HadMultipleCandidates, + bool ListInitialization, bool StdInitListInitialization, + bool ZeroInitialization, ConstructionKind ConstructKind, + SourceRange ParenOrBraceRange) + : Expr(SC, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(), + Ty->isDependentType(), Ty->isInstantiationDependentType(), + Ty->containsUnexpandedParameterPack()), + Constructor(Ctor), ParenOrBraceRange(ParenOrBraceRange), + NumArgs(Args.size()) { + CXXConstructExprBits.Elidable = Elidable; + CXXConstructExprBits.HadMultipleCandidates = HadMultipleCandidates; + CXXConstructExprBits.ListInitialization = ListInitialization; + CXXConstructExprBits.StdInitListInitialization = StdInitListInitialization; + CXXConstructExprBits.ZeroInitialization = ZeroInitialization; + CXXConstructExprBits.ConstructionKind = ConstructKind; + CXXConstructExprBits.Loc = Loc; - if (Args[i]->isValueDependent()) - ExprBits.ValueDependent = true; - if (Args[i]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (Args[i]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; + Stmt **TrailingArgs = getTrailingArgs(); + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + assert(Args[I] && "NULL argument in CXXConstructExpr!"); - this->Args[i] = Args[i]; - } + if (Args[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Args[I]->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (Args[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + TrailingArgs[I] = Args[I]; } } +CXXConstructExpr::CXXConstructExpr(StmtClass SC, EmptyShell Empty, + unsigned NumArgs) + : Expr(SC, Empty), NumArgs(NumArgs) {} + LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind, VarDecl *Var, SourceLocation EllipsisLoc) @@ -1044,12 +1226,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 +1243,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, } ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) - : Expr(ExprWithCleanupsClass, empty) { + : FullExpr(ExprWithCleanupsClass, empty) { ExprWithCleanupsBits.NumObjects = numObjects; } @@ -1078,22 +1255,22 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, return new (buffer) ExprWithCleanups(empty, numObjects); } -CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, - SourceLocation LParenLoc, - ArrayRef<Expr*> Args, - SourceLocation RParenLoc) +CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *TSI, + SourceLocation LParenLoc, + ArrayRef<Expr *> Args, + SourceLocation RParenLoc) : Expr(CXXUnresolvedConstructExprClass, - Type->getType().getNonReferenceType(), - (Type->getType()->isLValueReferenceType() + TSI->getType().getNonReferenceType(), + (TSI->getType()->isLValueReferenceType() ? VK_LValue - : Type->getType()->isRValueReferenceType() ? VK_XValue - : VK_RValue), + : TSI->getType()->isRValueReferenceType() ? VK_XValue + : VK_RValue), OK_Ordinary, - Type->getType()->isDependentType() || - Type->getType()->getContainedDeducedType(), - true, true, Type->getType()->containsUnexpandedParameterPack()), - Type(Type), LParenLoc(LParenLoc), RParenLoc(RParenLoc), - NumArgs(Args.size()) { + TSI->getType()->isDependentType() || + TSI->getType()->getContainedDeducedType(), + true, true, TSI->getType()->containsUnexpandedParameterPack()), + TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + CXXUnresolvedConstructExprBits.NumArgs = Args.size(); auto **StoredArgs = getTrailingObjects<Expr *>(); for (unsigned I = 0; I != Args.size(); ++I) { if (Args[I]->containsUnexpandedParameterPack()) @@ -1103,46 +1280,45 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, } } -CXXUnresolvedConstructExpr * -CXXUnresolvedConstructExpr::Create(const ASTContext &C, - TypeSourceInfo *Type, - SourceLocation LParenLoc, - ArrayRef<Expr*> Args, - SourceLocation RParenLoc) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Args.size())); - return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc, Args, RParenLoc); +CXXUnresolvedConstructExpr *CXXUnresolvedConstructExpr::Create( + const ASTContext &Context, TypeSourceInfo *TSI, SourceLocation LParenLoc, + ArrayRef<Expr *> Args, SourceLocation RParenLoc) { + void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(Args.size())); + return new (Mem) CXXUnresolvedConstructExpr(TSI, LParenLoc, Args, RParenLoc); } CXXUnresolvedConstructExpr * -CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &C, unsigned NumArgs) { - Stmt::EmptyShell Empty; - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumArgs)); - return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs); +CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &Context, + unsigned NumArgs) { + void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(NumArgs)); + return new (Mem) CXXUnresolvedConstructExpr(EmptyShell(), NumArgs); } -SourceLocation CXXUnresolvedConstructExpr::getLocStart() const { - return Type->getTypeLoc().getBeginLoc(); +SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const { + return TSI->getTypeLoc().getBeginLoc(); } CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( - const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, + const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) - : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue, + : Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue, OK_Ordinary, true, true, true, ((Base && Base->containsUnexpandedParameterPack()) || - (QualifierLoc && - QualifierLoc.getNestedNameSpecifier() - ->containsUnexpandedParameterPack()) || + (QualifierLoc && QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()) || MemberNameInfo.containsUnexpandedParameterPack())), - Base(Base), BaseType(BaseType), IsArrow(IsArrow), - HasTemplateKWAndArgsInfo(TemplateArgs != nullptr || - TemplateKWLoc.isValid()), - OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), - FirstQualifierFoundInScope(FirstQualifierFoundInScope), + Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc), MemberNameInfo(MemberNameInfo) { + CXXDependentScopeMemberExprBits.IsArrow = IsArrow; + CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo = + (TemplateArgs != nullptr) || TemplateKWLoc.isValid(); + CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope = + FirstQualifierFoundInScope != nullptr; + CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc; + if (TemplateArgs) { bool Dependent = true; bool InstantiationDependent = true; @@ -1156,56 +1332,54 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( TemplateKWLoc); } + + if (hasFirstQualifierFoundInScope()) + *getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope; } -CXXDependentScopeMemberExpr * -CXXDependentScopeMemberExpr::Create(const ASTContext &C, - Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs) { - bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); +CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( + EmptyShell Empty, bool HasTemplateKWAndArgsInfo, + bool HasFirstQualifierFoundInScope) + : Expr(CXXDependentScopeMemberExprClass, Empty) { + CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo = + HasTemplateKWAndArgsInfo; + CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope = + HasFirstQualifierFoundInScope; +} + +CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::Create( + const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, + DeclarationNameInfo MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + bool HasTemplateKWAndArgsInfo = + (TemplateArgs != nullptr) || TemplateKWLoc.isValid(); unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0; - std::size_t Size = - totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( - HasTemplateKWAndArgsInfo, NumTemplateArgs); + bool HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr; - void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); - return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, - IsArrow, OperatorLoc, - QualifierLoc, - TemplateKWLoc, - FirstQualifierFoundInScope, - MemberNameInfo, TemplateArgs); + unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc, NamedDecl *>( + HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope); + + void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); + return new (Mem) CXXDependentScopeMemberExpr( + Ctx, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc, + FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs); } -CXXDependentScopeMemberExpr * -CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C, - bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs) { +CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty( + const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope) { assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); - std::size_t Size = - totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( - HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); - auto *E = - new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(), - false, SourceLocation(), - NestedNameSpecifierLoc(), - SourceLocation(), nullptr, - DeclarationNameInfo(), nullptr); - E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; - return E; -} -bool CXXDependentScopeMemberExpr::isImplicitAccess() const { - if (!Base) - return true; + unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc, NamedDecl *>( + HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope); - return cast<Expr>(Base)->isImplicitCXXThis(); + void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); + return new (Mem) CXXDependentScopeMemberExpr( + EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope); } static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin, @@ -1225,19 +1399,15 @@ static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin, return true; } -UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C, - bool HasUnresolvedUsing, - Expr *Base, QualType BaseType, - bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End) +UnresolvedMemberExpr::UnresolvedMemberExpr( + const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base, + QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, + UnresolvedSetIterator End) : OverloadExpr( - UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc, + UnresolvedMemberExprClass, Context, QualifierLoc, TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End, // Dependent ((Base && Base->isTypeDependent()) || BaseType->isDependentType()), @@ -1246,14 +1416,22 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C, // Contains unexpanded parameter pack ((Base && Base->containsUnexpandedParameterPack()) || BaseType->containsUnexpandedParameterPack())), - IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), Base(Base), - BaseType(BaseType), OperatorLoc(OperatorLoc) { + Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) { + UnresolvedMemberExprBits.IsArrow = IsArrow; + UnresolvedMemberExprBits.HasUnresolvedUsing = HasUnresolvedUsing; + // Check whether all of the members are non-static member functions, // and if so, mark give this bound-member type instead of overload type. if (hasOnlyNonStaticMemberFunctions(Begin, End)) - setType(C.BoundMemberTy); + setType(Context.BoundMemberTy); } +UnresolvedMemberExpr::UnresolvedMemberExpr(EmptyShell Empty, + unsigned NumResults, + bool HasTemplateKWAndArgsInfo) + : OverloadExpr(UnresolvedMemberExprClass, Empty, NumResults, + HasTemplateKWAndArgsInfo) {} + bool UnresolvedMemberExpr::isImplicitAccess() const { if (!Base) return true; @@ -1262,39 +1440,37 @@ bool UnresolvedMemberExpr::isImplicitAccess() const { } UnresolvedMemberExpr *UnresolvedMemberExpr::Create( - const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, - bool IsArrow, SourceLocation OperatorLoc, + const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base, + QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) { + unsigned NumResults = End - Begin; bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); - std::size_t Size = - totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( - HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0); - - void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr)); + unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0; + unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc>( + NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs); + void *Mem = Context.Allocate(Size, alignof(UnresolvedMemberExpr)); return new (Mem) UnresolvedMemberExpr( - C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, - TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End); + Context, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, + QualifierLoc, TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End); } -UnresolvedMemberExpr * -UnresolvedMemberExpr::CreateEmpty(const ASTContext &C, - bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs) { +UnresolvedMemberExpr *UnresolvedMemberExpr::CreateEmpty( + const ASTContext &Context, unsigned NumResults, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); - std::size_t Size = - totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( - HasTemplateKWAndArgsInfo, NumTemplateArgs); - - void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr)); - auto *E = new (Mem) UnresolvedMemberExpr(EmptyShell()); - E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; - return E; + unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc>( + NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs); + void *Mem = Context.Allocate(Size, alignof(UnresolvedMemberExpr)); + return new (Mem) + UnresolvedMemberExpr(EmptyShell(), NumResults, HasTemplateKWAndArgsInfo); } -CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { +CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() { // Unlike for UnresolvedLookupExpr, it is very easy to re-derive this. // If there was a nested name specifier, it names the naming class. @@ -1448,4 +1624,37 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C, return new (Mem) TypeTraitExpr(EmptyShell()); } -void ArrayTypeTraitExpr::anchor() {} +CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, + ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation RP, + unsigned MinNumArgs) + : CallExpr(CUDAKernelCallExprClass, Fn, /*PreArgs=*/Config, Args, Ty, VK, + RP, MinNumArgs, NotADL) {} + +CUDAKernelCallExpr::CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty) + : CallExpr(CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs, + Empty) {} + +CUDAKernelCallExpr * +CUDAKernelCallExpr::Create(const ASTContext &Ctx, Expr *Fn, CallExpr *Config, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation RP, unsigned MinNumArgs) { + // Allocate storage for the trailing objects of CallExpr. + unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs); + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs); + void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects, + alignof(CUDAKernelCallExpr)); + return new (Mem) CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, MinNumArgs); +} + +CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, + EmptyShell Empty) { + // Allocate storage for the trailing objects of CallExpr. + unsigned SizeOfTrailingObjects = + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs); + void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects, + alignof(CUDAKernelCallExpr)); + return new (Mem) CUDAKernelCallExpr(NumArgs, Empty); +} diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index e50dd9c79d11..e1d6a1c9edcc 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 44cf75dbd25b..da093ff22c12 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(); @@ -350,6 +352,7 @@ namespace { /// Get the type of the designated object. QualType getType(ASTContext &Ctx) const { + assert(!Invalid && "invalid designator has no subobject type"); return MostDerivedPathLength == Entries.size() ? MostDerivedType : Ctx.getRecordType(getAsBaseClass(Entries.back())); @@ -504,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. @@ -719,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. @@ -758,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 @@ -792,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; @@ -831,7 +826,7 @@ namespace { bool nextStep(const Stmt *S) { if (!StepsLeft) { - FFDiag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded); + FFDiag(S->getBeginLoc(), diag::note_constexpr_step_limit_exceeded); return false; } --StepsLeft; @@ -873,7 +868,6 @@ namespace { case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_PotentialConstantExpressionUnevaluated: - case EM_OffsetFold: HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -965,7 +959,6 @@ namespace { case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: - case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -984,7 +977,6 @@ namespace { case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: case EM_ConstantFold: - case EM_OffsetFold: return true; case EM_PotentialConstantExpression: @@ -1020,7 +1012,6 @@ namespace { case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: - case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -1092,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 @@ -1299,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: @@ -1404,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) { @@ -2088,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; } @@ -2553,8 +2568,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, if (Info.checkingPotentialConstantExpression()) return false; // FIXME: implement capture evaluation during constant expr evaluation. - Info.FFDiag(E->getLocStart(), - diag::note_unimplemented_constexpr_lambda_feature_ast) + Info.FFDiag(E->getBeginLoc(), + diag::note_unimplemented_constexpr_lambda_feature_ast) << "captures not currently allowed"; return false; } @@ -2754,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). @@ -3432,19 +3439,31 @@ struct CompoundAssignSubobjectHandler { if (!checkConst(SubobjType)) return false; - if (!SubobjType->isIntegerType() || !RHS.isInt()) { + if (!SubobjType->isIntegerType()) { // We don't support compound assignment on integer-cast-to-pointer // values. Info.FFDiag(E); return false; } - APSInt LHS = HandleIntToIntCast(Info, E, PromotedLHSType, - SubobjType, Value); - if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS)) - return false; - Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS); - return true; + if (RHS.isInt()) { + APSInt LHS = + HandleIntToIntCast(Info, E, PromotedLHSType, SubobjType, Value); + if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS)) + return false; + Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS); + return true; + } else if (RHS.isFloat()) { + APFloat FValue(0.0); + return HandleIntToFloatCast(Info, E, SubobjType, Value, PromotedLHSType, + FValue) && + handleFloatFloatBinOp(Info, E, FValue, Opcode, RHS.getFloat()) && + HandleFloatToIntCast(Info, E, PromotedLHSType, FValue, SubobjType, + Value); + } + + Info.FFDiag(E); + return false; } bool found(APFloat &Value, QualType SubobjType) { return checkConst(SubobjType) && @@ -3844,8 +3863,8 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { const Expr *InitE = VD->getInit(); if (!InitE) { - Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized) - << false << VD->getType(); + Info.FFDiag(VD->getBeginLoc(), diag::note_constexpr_uninitialized) + << false << VD->getType(); Val = APValue(); return false; } @@ -3990,7 +4009,8 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, case ESR_CaseNotFound: // This can only happen if the switch case is nested within a statement // expression. We have no intention of supporting that. - Info.FFDiag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); + Info.FFDiag(Found->getBeginLoc(), + diag::note_constexpr_stmt_expr_unsupported); return ESR_Failed; } llvm_unreachable("Invalid EvalStmtResult!"); @@ -4081,7 +4101,7 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, return ESR_Succeeded; } - Info.FFDiag(S->getLocStart()); + Info.FFDiag(S->getBeginLoc()); return ESR_Failed; case Stmt::NullStmtClass: @@ -4215,6 +4235,13 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const CXXForRangeStmt *FS = cast<CXXForRangeStmt>(S); BlockScopeRAII Scope(Info); + // Evaluate the init-statement if present. + if (FS->getInit()) { + EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getInit()); + if (ESR != ESR_Succeeded) + return ESR; + } + // Initialize the __range variable. EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getRangeStmt()); if (ESR != ESR_Succeeded) @@ -4279,6 +4306,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); } } @@ -4321,10 +4351,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() && @@ -4429,7 +4462,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc, if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), RHS, RHSValue)) return false; - if (!handleAssignment(Info, Args[0], *This, MD->getThisType(Info.Ctx), + if (!handleAssignment(Info, Args[0], *This, MD->getThisType(), RHSValue)) return false; This->moveInto(Result); @@ -4451,7 +4484,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc, if (ESR == ESR_Succeeded) { if (Callee->getReturnType()->isVoidType()) return true; - Info.FFDiag(Callee->getLocEnd(), diag::note_constexpr_no_return); + Info.FFDiag(Callee->getEndLoc(), diag::note_constexpr_no_return); } return ESR == ESR_Returned; } @@ -4722,6 +4755,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) @@ -5076,8 +5111,8 @@ public: if (BI + 1 == BE) { const Expr *FinalExpr = dyn_cast<Expr>(*BI); if (!FinalExpr) { - Info.FFDiag((*BI)->getLocStart(), - diag::note_constexpr_stmt_expr_unsupported); + Info.FFDiag((*BI)->getBeginLoc(), + diag::note_constexpr_stmt_expr_unsupported); return false; } return this->Visit(FinalExpr); @@ -5091,8 +5126,8 @@ public: // 'break', or 'continue', it would be nice to propagate that to // the outer statement evaluation rather than bailing out. if (ESR != ESR_Failed) - Info.FFDiag((*BI)->getLocStart(), - diag::note_constexpr_stmt_expr_unsupported); + Info.FFDiag((*BI)->getBeginLoc(), + diag::note_constexpr_stmt_expr_unsupported); return false; } } @@ -5625,8 +5660,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); @@ -5852,11 +5889,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(); @@ -5954,21 +5987,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 @@ -5985,7 +6032,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. @@ -6046,8 +6093,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) { @@ -6077,7 +6124,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: @@ -6109,9 +6157,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; @@ -6207,6 +6273,20 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!N) return true; + // Otherwise, if either of the operands is null, we can't proceed. Don't + // try to determine the type of the copied objects, because there aren't + // any. + if (!Src.Base || !Dest.Base) { + APValue Val; + (!Src.Base ? Src : Dest).moveInto(Val); + Info.FFDiag(E, diag::note_constexpr_memcpy_null) + << Move << WChar << !!Src.Base + << Val.getAsString(Info.Ctx, E->getArg(0)->getType()); + return false; + } + if (Src.Designator.Invalid || Dest.Designator.Invalid) + return false; + // We require that Src and Dest are both pointers to arrays of // trivially-copyable type. (For the wide version, the designator will be // invalid if the designated object is not a wchar_t.) @@ -6216,6 +6296,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; @@ -7320,6 +7404,8 @@ public: // Visitor Methods //===--------------------------------------------------------------------===// + bool VisitConstantExpr(const ConstantExpr *E); + bool VisitIntegerLiteral(const IntegerLiteral *E) { return Success(E->getValue(), E); } @@ -7619,6 +7705,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: @@ -8023,7 +8112,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 @@ -8057,6 +8146,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); @@ -8091,7 +8185,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: @@ -8103,6 +8196,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: { @@ -8116,9 +8215,15 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BI__builtin_classify_type: return Success((int)EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E); - // FIXME: BI__builtin_clrsb - // FIXME: BI__builtin_clrsbl - // FIXME: BI__builtin_clrsbll + case Builtin::BI__builtin_clrsb: + case Builtin::BI__builtin_clrsbl: + case Builtin::BI__builtin_clrsbll: { + APSInt Val; + if (!EvaluateInteger(E->getArg(0), Val, Info)) + return false; + + return Success(Val.getBitWidth() - Val.getMinSignedBits(), E); + } case Builtin::BI__builtin_clz: case Builtin::BI__builtin_clzl: @@ -8133,8 +8238,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: @@ -8314,8 +8431,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 && @@ -8326,6 +8441,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 && @@ -8336,11 +8533,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. @@ -8351,8 +8547,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. @@ -9343,11 +9538,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: { @@ -9536,11 +9734,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: @@ -9575,6 +9773,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; @@ -9697,8 +9903,7 @@ bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) { SmallString<64> S; FixedPointValueToString(S, Value, - Info.Ctx.getTypeInfo(E->getType()).Width, - /*Radix=*/10); + Info.Ctx.getTypeInfo(E->getType()).Width); Info.CCEDiag(E, diag::note_constexpr_overflow) << S << E->getType(); if (Info.noteUndefinedBehavior()) return false; } @@ -10071,11 +10276,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: @@ -10236,7 +10442,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; @@ -10317,7 +10523,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; @@ -10693,19 +10899,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, @@ -10715,24 +10948,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, @@ -10790,6 +11009,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); @@ -10819,28 +11039,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); } } @@ -10893,9 +11131,13 @@ 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->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); return NoDiag(); } @@ -10903,7 +11145,7 @@ static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); if (!E->getType()->isIntegralOrEnumerationType()) - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); switch (E->getStmtClass()) { #define ABSTRACT_STMT(Node) @@ -10987,7 +11229,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::CoawaitExprClass: case Expr::DependentCoawaitExprClass: case Expr::CoyieldExprClass: - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); case Expr::InitListExprClass: { // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the @@ -10997,7 +11239,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { if (E->isRValue()) if (cast<InitListExpr>(E)->getNumInits() == 1) return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx); - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } case Expr::SizeOfPackExprClass: @@ -11009,6 +11251,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: @@ -11032,7 +11277,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { const CallExpr *CE = cast<CallExpr>(E); if (CE->getBuiltinCallee()) return CheckEvalInICE(E, Ctx); - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } case Expr::DeclRefExprClass: { if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) @@ -11062,7 +11307,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); } } - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } case Expr::UnaryOperatorClass: { const UnaryOperator *Exp = cast<UnaryOperator>(E); @@ -11077,7 +11322,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { // C99 6.6/3 allows increment and decrement within unevaluated // subexpressions of constant expressions, but they can never be ICEs // because an ICE cannot contain an lvalue operand. - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); case UO_Extension: case UO_LNot: case UO_Plus: @@ -11087,9 +11332,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 @@ -11104,7 +11347,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E); if ((Exp->getKind() == UETT_SizeOf) && Exp->getTypeOfArgument()->isVariableArrayType()) - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); return NoDiag(); } case Expr::BinaryOperatorClass: { @@ -11126,7 +11369,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { // C99 6.6/3 allows assignments within unevaluated subexpressions of // constant expressions, but they can never be ICEs because an ICE cannot // contain an lvalue operand. - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); case BO_Mul: case BO_Div: @@ -11155,11 +11398,11 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) - return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); if (REval.isSigned() && REval.isAllOnesValue()) { llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) - return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); } } } @@ -11168,10 +11411,10 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { // C99 6.6p3 introduces a strange edge case: comma can be in an ICE // if it isn't evaluated. if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) - return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); } else { // In both C89 and C++, commas in ICEs are illegal. - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } } return Worst(LHSResult, RHSResult); @@ -11193,7 +11436,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: @@ -11216,7 +11459,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { if (FL->getValue().convertToInteger(IgnoredVal, llvm::APFloat::rmTowardZero, &Ignored) & APFloat::opInvalidOp) - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); return NoDiag(); } } @@ -11229,7 +11472,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case CK_IntegralCast: return CheckICE(SubExpr, Ctx); default: - return ICEDiag(IK_NotICE, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getBeginLoc()); } } case Expr::BinaryConditionalOperatorClass: { @@ -11330,12 +11573,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; } @@ -11421,6 +11672,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 ae28c588ca31..12e6bfc041a4 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 000000000000..04bd48f14a2a --- /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 000000000000..9da829adcb49 --- /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 2dc04f2f3d86..98c843db31d6 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 { @@ -323,7 +317,7 @@ class CXXNameMangler { AdditionalAbiTags->end()); } - llvm::sort(TagList.begin(), TagList.end()); + llvm::sort(TagList); TagList.erase(std::unique(TagList.begin(), TagList.end()), TagList.end()); writeSortedUniqueAbiTags(Out, TagList); @@ -339,7 +333,7 @@ class CXXNameMangler { } const AbiTagList &getSortedUniqueUsedAbiTags() { - llvm::sort(UsedAbiTags.begin(), UsedAbiTags.end()); + llvm::sort(UsedAbiTags); UsedAbiTags.erase(std::unique(UsedAbiTags.begin(), UsedAbiTags.end()), UsedAbiTags.end()); return UsedAbiTags; @@ -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; } @@ -721,10 +704,8 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { if (FD->hasAttr<EnableIfAttr>()) { FunctionTypeDepthState Saved = FunctionTypeDepth.push(); Out << "Ua9enable_ifI"; - // FIXME: specific_attr_iterator iterates in reverse order. Fix that and use - // it here. - for (AttrVec::const_reverse_iterator I = FD->getAttrs().rbegin(), - E = FD->getAttrs().rend(); + for (AttrVec::const_iterator I = FD->getAttrs().begin(), + E = FD->getAttrs().end(); I != E; ++I) { EnableIfAttr *EIA = dyn_cast<EnableIfAttr>(*I); if (!EIA) @@ -1522,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(); @@ -2654,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" } } @@ -2662,16 +2648,12 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_C: return ""; - case CC_X86StdCall: - case CC_X86FastCall: - case CC_X86ThisCall: case CC_X86VectorCall: case CC_X86Pascal: - case CC_Win64: - case CC_X86_64SysV: case CC_X86RegCall: case CC_AAPCS: case CC_AAPCS_VFP: + case CC_AArch64VectorCall: case CC_IntelOclBicc: case CC_SpirFunction: case CC_OpenCLKernel: @@ -2680,6 +2662,22 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { // FIXME: we should be mangling all of the above. return ""; + case CC_X86ThisCall: + // FIXME: To match mingw GCC, thiscall should only be mangled in when it is + // used explicitly. At this point, we don't have that much information in + // the AST, since clang tends to bake the convention into the canonical + // function type. thiscall only rarely used explicitly, so don't mangle it + // for now. + return ""; + + case CC_X86StdCall: + return "stdcall"; + case CC_X86FastCall: + return "fastcall"; + case CC_X86_64SysV: + return "sysv_abi"; + case CC_Win64: + return "ms_abi"; case CC_Swift: return "swiftcall"; } @@ -2737,7 +2735,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. @@ -3526,6 +3524,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: @@ -3883,6 +3885,7 @@ recurse: case UETT_SizeOf: Out << 's'; break; + case UETT_PreferredAlignOf: case UETT_AlignOf: Out << 'a'; break; diff --git a/lib/AST/Linkage.h b/lib/AST/Linkage.h index e6489c7ef2b3..8ad748bcc4a2 100644 --- a/lib/AST/Linkage.h +++ b/lib/AST/Linkage.h @@ -20,6 +20,7 @@ #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" namespace clang { /// Kinds of LV computation. The linkage side of the computation is @@ -36,6 +37,8 @@ struct LVComputationKind { /// in computing linkage. unsigned IgnoreAllVisibility : 1; + enum { NumLVComputationKindBits = 3 }; + explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK) : ExplicitKind(EK), IgnoreExplicitVisibility(false), IgnoreAllVisibility(false) {} @@ -78,12 +81,14 @@ class LinkageComputer { // using C = Foo<B, B>; // using D = Foo<C, C>; // - // The unsigned represents an LVComputationKind. - using QueryType = std::pair<const NamedDecl *, unsigned>; + // The integer represents an LVComputationKind. + using QueryType = + llvm::PointerIntPair<const NamedDecl *, + LVComputationKind::NumLVComputationKindBits>; llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo; static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) { - return std::make_pair(ND, Kind.toBits()); + return QueryType(ND, Kind.toBits()); } llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND, diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp index b0e5146e8194..bb29bffc1b8f 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 5db51b5cb384..92e9679e49aa 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -29,6 +29,7 @@ #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/JamCRC.h" +#include "llvm/Support/xxhash.h" #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" @@ -127,10 +128,10 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext { llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds; llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds; llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds; + SmallString<16> AnonymousNamespaceHash; public: - MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) - : MicrosoftMangleContext(Context, Diags) {} + MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags); bool shouldMangleCXXName(const NamedDecl *D) override; bool shouldMangleStringLiteral(const StringLiteral *SL) override; void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override; @@ -238,6 +239,12 @@ public: return Result.first->second; } + /// Return a character sequence that is (somewhat) unique to the TU suitable + /// for mangling anonymous namespaces. + StringRef getAnonymousNamespaceHash() const { + return AnonymousNamespaceHash; + } + private: void mangleInitFiniStub(const VarDecl *D, char CharCode, raw_ostream &Out); }; @@ -302,13 +309,15 @@ 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 mangleAddressSpaceType(QualType T, Qualifiers Quals, SourceRange Range); void mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM = QMM_Mangle); void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = nullptr, - bool ForceThisQuals = false); + bool ForceThisQuals = false, + bool MangleExceptionSpec = true); void mangleNestedName(const NamedDecl *ND); private: @@ -368,9 +377,39 @@ private: void mangleObjCProtocol(const ObjCProtocolDecl *PD); void mangleObjCLifetime(const QualType T, Qualifiers Quals, SourceRange Range); + void mangleObjCKindOfType(const ObjCObjectType *T, Qualifiers Quals, + SourceRange Range); }; } +MicrosoftMangleContextImpl::MicrosoftMangleContextImpl(ASTContext &Context, + DiagnosticsEngine &Diags) + : MicrosoftMangleContext(Context, Diags) { + // To mangle anonymous namespaces, hash the path to the main source file. The + // path should be whatever (probably relative) path was passed on the command + // line. The goal is for the compiler to produce the same output regardless of + // working directory, so use the uncanonicalized relative path. + // + // It's important to make the mangled names unique because, when CodeView + // debug info is in use, the debugger uses mangled type names to distinguish + // between otherwise identically named types in anonymous namespaces. + // + // These symbols are always internal, so there is no need for the hash to + // match what MSVC produces. For the same reason, clang is free to change the + // hash at any time without breaking compatibility with old versions of clang. + // The generated names are intended to look similar to what MSVC generates, + // which are something like "?A0x01234567@". + SourceManager &SM = Context.getSourceManager(); + if (const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID())) { + // Truncate the hash so we get 8 characters of hexadecimal. + uint32_t TruncatedHash = uint32_t(xxHash64(FE->getName())); + AnonymousNamespaceHash = llvm::utohexstr(TruncatedHash); + } else { + // If we don't have a path to the main file, we'll just use 0. + AnonymousNamespaceHash = "0"; + } +} + bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { LanguageLinkage L = FD->getLanguageLinkage(); @@ -475,7 +514,7 @@ void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD, mangleFunctionClass(FD); - mangleFunctionType(FT, FD); + mangleFunctionType(FT, FD, false, false); } else { Out << '9'; } @@ -785,7 +824,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { if (NS->isAnonymousNamespace()) { - Out << "?A@"; + Out << "?A0x" << Context.getAnonymousNamespaceHash() << '@'; break; } } @@ -905,8 +944,14 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - llvm_unreachable("Can't mangle Objective-C selector names here!"); + case DeclarationName::ObjCMultiArgSelector: { + // This is reachable only when constructing an outlined SEH finally + // block. Nothing depends on this mangling and it's used only with + // functinos with internal linkage. + llvm::SmallString<64> Name; + mangleSourceName(Name.str()); + break; + } case DeclarationName::CXXConstructorName: if (isStructorDecl(ND)) { @@ -1027,7 +1072,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"; @@ -1322,7 +1367,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; @@ -1343,9 +1388,16 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs( assert(TPL->size() == TemplateArgs.size() && "size mismatch between args and parms!"); - unsigned Idx = 0; - for (const TemplateArgument &TA : TemplateArgs.asArray()) - mangleTemplateArg(TD, TA, TPL->getParam(Idx++)); + for (size_t i = 0; i < TemplateArgs.size(); ++i) { + const TemplateArgument &TA = TemplateArgs[i]; + + // Separate consecutive packs by $$Z. + if (i > 0 && TA.getKind() == TemplateArgument::Pack && + TemplateArgs[i - 1].getKind() == TemplateArgument::Pack) + Out << "$$Z"; + + mangleTemplateArg(TD, TA, TPL->getParam(i)); + } } void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, @@ -1471,9 +1523,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, @@ -1502,7 +1554,24 @@ 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, + Qualifiers Quals, + SourceRange Range) { + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + + Stream << "?$"; + Extra.mangleSourceName("KindOf"); + Extra.mangleType(QualType(T, 0) + .stripObjCKindOfType(getASTContext()) + ->getAs<ObjCObjectType>(), + Quals, Range); + + mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); } void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, @@ -1698,7 +1767,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) { @@ -1710,12 +1779,77 @@ void MicrosoftCXXNameMangler::manglePassObjectSizeArg( } } +void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T, + Qualifiers Quals, + SourceRange Range) { + // Address space is mangled as an unqualified templated type in the __clang + // namespace. The demangled version of this is: + // In the case of a language specific address space: + // __clang::struct _AS[language_addr_space]<Type> + // where: + // <language_addr_space> ::= <OpenCL-addrspace> | <CUDA-addrspace> + // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" | + // "private"| "generic" ] + // <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ] + // Note that the above were chosen to match the Itanium mangling for this. + // + // In the case of a non-language specific address space: + // __clang::struct _AS<TargetAS, Type> + assert(Quals.hasAddressSpace() && "Not valid without address space"); + llvm::SmallString<32> ASMangling; + llvm::raw_svector_ostream Stream(ASMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + Stream << "?$"; + + LangAS AS = Quals.getAddressSpace(); + if (Context.getASTContext().addressSpaceMapManglingFor(AS)) { + unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS); + Extra.mangleSourceName("_AS"); + Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(TargetAS), + /*IsBoolean*/ false); + } else { + switch (AS) { + default: + llvm_unreachable("Not a language specific address space"); + case LangAS::opencl_global: + Extra.mangleSourceName("_ASCLglobal"); + break; + case LangAS::opencl_local: + Extra.mangleSourceName("_ASCLlocal"); + break; + case LangAS::opencl_constant: + Extra.mangleSourceName("_ASCLconstant"); + break; + case LangAS::opencl_private: + Extra.mangleSourceName("_ASCLprivate"); + break; + case LangAS::opencl_generic: + Extra.mangleSourceName("_ASCLgeneric"); + break; + case LangAS::cuda_device: + Extra.mangleSourceName("_ASCUdevice"); + break; + case LangAS::cuda_constant: + Extra.mangleSourceName("_ASCUconstant"); + break; + case LangAS::cuda_shared: + Extra.mangleSourceName("_ASCUshared"); + break; + } + } + + Extra.mangleType(T, Range, QMM_Escape); + mangleQualifiers(Qualifiers(), false); + mangleArtificialTagType(TTK_Struct, ASMangling, {"__clang"}); +} + void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM) { // Don't use the canonical types. MSVC includes things like 'const' on // pointer arguments to function pointers that canonicalization strips away. T = T.getDesugaredType(getASTContext()); Qualifiers Quals = T.getLocalQualifiers(); + if (const ArrayType *AT = getASTContext().getAsArrayType(T)) { // If there were any Quals, getAsArrayType() pushed them onto the array // element type. @@ -1884,13 +2018,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) \ @@ -1900,35 +2034,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: @@ -1989,7 +2128,8 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, const FunctionDecl *D, - bool ForceThisQuals) { + bool ForceThisQuals, + bool MangleExceptionSpec) { // <function-type> ::= <this-cvr-qualifiers> <calling-convention> // <return-type> <argument-list> <throw-spec> const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T); @@ -2021,7 +2161,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); @@ -2122,7 +2262,12 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, Out << '@'; } - mangleThrowSpecification(Proto); + if (MangleExceptionSpec && getASTContext().getLangOpts().CPlusPlus17 && + getASTContext().getLangOpts().isCompatibleWithMSVC( + LangOptions::MSVC2017_5)) + mangleThrowSpecification(Proto); + else + Out << 'Z'; } void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { @@ -2227,15 +2372,15 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { mangleCallingConvention(T->getCallConv()); } + void MicrosoftCXXNameMangler::mangleThrowSpecification( const FunctionProtoType *FT) { - // <throw-spec> ::= Z # throw(...) (default) - // ::= @ # throw() or __declspec/__attribute__((nothrow)) - // ::= <type>+ - // NOTE: Since the Microsoft compiler ignores throw specifications, they are - // all actually mangled as 'Z'. (They're ignored because their associated - // functionality isn't implemented, and probably never will be.) - Out << 'Z'; + // <throw-spec> ::= Z # (default) + // ::= _E # noexcept + if (FT->canThrow()) + Out << 'Z'; + else + Out << "_E"; } void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T, @@ -2285,7 +2430,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>]}? @ @@ -2416,7 +2561,11 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals, QualType PointeeType = T->getPointeeType(); manglePointerCVQualifiers(Quals); manglePointerExtQualifiers(Quals, PointeeType); - mangleType(PointeeType, Range); + + if (PointeeType.getQualifiers().hasAddressSpace()) + mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range); + else + mangleType(PointeeType, Range); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, @@ -2471,10 +2620,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 @@ -2487,7 +2636,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; } @@ -2502,18 +2651,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'); + } } } @@ -2532,7 +2683,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"}); } } @@ -2575,9 +2726,12 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, mangleName(T->getDecl()); } -void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers, - SourceRange Range) { - if (T->qual_empty()) +void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, + Qualifiers Quals, SourceRange Range) { + if (T->isKindOfType()) + return mangleObjCKindOfType(T, Quals, Range); + + if (T->qual_empty() && !T->isSpecialized()) return mangleType(T->getBaseType(), Range, QMM_Drop); ArgBackRefMap OuterArgsContext; @@ -2598,6 +2752,11 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers, for (const auto &Q : T->quals()) mangleObjCProtocol(Q); + + if (T->isSpecialized()) + for (const auto &TA : T->getTypeArgs()) + mangleType(TA, Range, QMM_Drop); + Out << '@'; Out << '@'; @@ -2728,7 +2887,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, @@ -2780,14 +2939,14 @@ void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D, // <vtordisp-shift> ::= <offset-to-vtordisp> // <vtordispex-shift> ::= <offset-to-vbptr> <vbase-offset-offset> // <offset-to-vtordisp> -static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, +static void mangleThunkThisAdjustment(AccessSpecifier AS, const ThisAdjustment &Adjustment, MicrosoftCXXNameMangler &Mangler, raw_ostream &Out) { if (!Adjustment.Virtual.isEmpty()) { Out << '$'; char AccessSpec; - switch (MD->getAccess()) { + switch (AS) { case AS_none: llvm_unreachable("Unsupported access specifier"); case AS_private: @@ -2815,7 +2974,7 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, Mangler.mangleNumber(-static_cast<uint32_t>(Adjustment.NonVirtual)); } } else if (Adjustment.NonVirtual != 0) { - switch (MD->getAccess()) { + switch (AS) { case AS_none: llvm_unreachable("Unsupported access specifier"); case AS_private: @@ -2829,7 +2988,7 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, } Mangler.mangleNumber(-static_cast<uint32_t>(Adjustment.NonVirtual)); } else { - switch (MD->getAccess()) { + switch (AS) { case AS_none: llvm_unreachable("Unsupported access specifier"); case AS_private: @@ -2860,7 +3019,13 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << '?'; Mangler.mangleName(MD); - mangleThunkThisAdjustment(MD, Thunk.This, Mangler, MHO); + + // Usually the thunk uses the access specifier of the new method, but if this + // is a covariant return thunk, then MSVC always uses the public access + // specifier, and we do the same. + AccessSpecifier AS = Thunk.Return.isEmpty() ? MD->getAccess() : AS_public; + mangleThunkThisAdjustment(AS, Thunk.This, Mangler, MHO); + if (!Thunk.Return.isEmpty()) assert(Thunk.Method != nullptr && "Thunk info should hold the overridee decl"); @@ -2881,7 +3046,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk( MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type); Mangler.getStream() << "??_E"; Mangler.mangleName(DD->getParent()); - mangleThunkThisAdjustment(DD, Adjustment, Mangler, MHO); + mangleThunkThisAdjustment(DD->getAccess(), Adjustment, Mangler, MHO); Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD); } @@ -3175,10 +3340,13 @@ void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D, msvc_hashing_ostream MHO(Out); MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "??__" << CharCode; - Mangler.mangleName(D); if (D->isStaticDataMember()) { + Mangler.getStream() << '?'; + Mangler.mangleName(D); Mangler.mangleVariableEncoding(D); - Mangler.getStream() << '@'; + Mangler.getStream() << "@@"; + } else { + Mangler.mangleName(D); } // This is the function class mangling. These stubs are global, non-variadic, // cdecl functions that return void and take no args. diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp index 94ad87b6e337..5b8300893e2d 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; @@ -607,3 +610,11 @@ Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids, } return Sel; } + +Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const { + if (Sel.isNull()) { + IdentifierInfo *Ident = &Ctx.Idents.get(Id); + Sel = Ctx.Selectors.getSelector(0, &Ident); + } + return Sel; +} diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index a514d57b6b6b..42f6a133d717 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 @@ -446,9 +462,9 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { } TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { - assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || - Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && - "Nested-name-specifier location is not a type"); + if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec && + Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate) + return TypeLoc(); // The "void*" that points at the TypeLoc data. unsigned Offset = getDataLength(Qualifier->getPrefix()); @@ -547,6 +563,7 @@ operator=(const NestedNameSpecifierLocBuilder &Other) { } // Deep copy. + BufferSize = 0; Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, BufferCapacity); return *this; diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index e710d3780337..a4c344ce0a9b 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -32,12 +32,24 @@ void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) { ID.AddString(II->getName()); } -void ODRHash::AddDeclarationName(DeclarationName Name) { +void ODRHash::AddDeclarationName(DeclarationName Name, bool TreatAsDecl) { + if (TreatAsDecl) + // Matches the NamedDecl check in AddDecl + AddBoolean(true); + + AddDeclarationNameImpl(Name); + + if (TreatAsDecl) + // Matches the ClassTemplateSpecializationDecl check in AddDecl + AddBoolean(false); +} + +void ODRHash::AddDeclarationNameImpl(DeclarationName Name) { // Index all DeclarationName and use index numbers to refer to them. 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; } @@ -405,6 +417,7 @@ public: void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { AddDecl(D->getTemplatedDecl()); + ID.AddInteger(D->getTemplatedDecl()->getODRHash()); Inherited::VisitFunctionTemplateDecl(D); } @@ -552,11 +565,27 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function, !Function->isDefaulted() && !Function->isDeleted() && !Function->isLateTemplateParsed(); AddBoolean(HasBody); - if (HasBody) { - auto *Body = Function->getBody(); - AddBoolean(Body); - if (Body) - AddStmt(Body); + if (!HasBody) { + return; + } + + auto *Body = Function->getBody(); + AddBoolean(Body); + if (Body) + AddStmt(Body); + + // Filter out sub-Decls which will not be processed in order to get an + // accurate count of Decl's. + llvm::SmallVector<const Decl *, 16> Decls; + for (Decl *SubDecl : Function->decls()) { + if (isWhitelistedDecl(SubDecl, Function)) { + Decls.push_back(SubDecl); + } + } + + ID.AddInteger(Decls.size()); + for (auto SubDecl : Decls) { + AddSubDecl(SubDecl); } } @@ -592,13 +621,24 @@ void ODRHash::AddDecl(const Decl *D) { assert(D && "Expecting non-null pointer."); D = D->getCanonicalDecl(); - if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { - AddDeclarationName(ND->getDeclName()); + const NamedDecl *ND = dyn_cast<NamedDecl>(D); + AddBoolean(ND); + if (!ND) { + ID.AddInteger(D->getKind()); return; } - ID.AddInteger(D->getKind()); - // TODO: Handle non-NamedDecl here. + AddDeclarationName(ND->getDeclName()); + + const auto *Specialization = + dyn_cast<ClassTemplateSpecializationDecl>(D); + AddBoolean(Specialization); + if (Specialization) { + const TemplateArgumentList &List = Specialization->getTemplateArgs(); + ID.AddInteger(List.size()); + for (const TemplateArgument &TA : List.asArray()) + AddTemplateArgument(TA); + } } namespace { @@ -700,11 +740,67 @@ public: VisitArrayType(T); } + void VisitAttributedType(const AttributedType *T) { + ID.AddInteger(T->getAttrKind()); + AddQualType(T->getModifiedType()); + AddQualType(T->getEquivalentType()); + + VisitType(T); + } + + void VisitBlockPointerType(const BlockPointerType *T) { + AddQualType(T->getPointeeType()); + VisitType(T); + } + void VisitBuiltinType(const BuiltinType *T) { ID.AddInteger(T->getKind()); VisitType(T); } + void VisitComplexType(const ComplexType *T) { + AddQualType(T->getElementType()); + VisitType(T); + } + + void VisitDecltypeType(const DecltypeType *T) { + AddStmt(T->getUnderlyingExpr()); + AddQualType(T->getUnderlyingType()); + VisitType(T); + } + + void VisitDependentDecltypeType(const DependentDecltypeType *T) { + VisitDecltypeType(T); + } + + void VisitDeducedType(const DeducedType *T) { + AddQualType(T->getDeducedType()); + VisitType(T); + } + + void VisitAutoType(const AutoType *T) { + ID.AddInteger((unsigned)T->getKeyword()); + VisitDeducedType(T); + } + + void VisitDeducedTemplateSpecializationType( + const DeducedTemplateSpecializationType *T) { + Hash.AddTemplateName(T->getTemplateName()); + VisitDeducedType(T); + } + + void VisitDependentAddressSpaceType(const DependentAddressSpaceType *T) { + AddQualType(T->getPointeeType()); + AddStmt(T->getAddrSpaceExpr()); + VisitType(T); + } + + void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) { + AddQualType(T->getElementType()); + AddStmt(T->getSizeExpr()); + VisitType(T); + } + void VisitFunctionType(const FunctionType *T) { AddQualType(T->getReturnType()); T->getExtInfo().Profile(ID); @@ -726,6 +822,74 @@ public: VisitFunctionType(T); } + void VisitInjectedClassNameType(const InjectedClassNameType *T) { + AddDecl(T->getDecl()); + VisitType(T); + } + + void VisitMemberPointerType(const MemberPointerType *T) { + AddQualType(T->getPointeeType()); + AddType(T->getClass()); + VisitType(T); + } + + void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { + AddQualType(T->getPointeeType()); + VisitType(T); + } + + void VisitObjCObjectType(const ObjCObjectType *T) { + AddDecl(T->getInterface()); + + auto TypeArgs = T->getTypeArgsAsWritten(); + ID.AddInteger(TypeArgs.size()); + for (auto Arg : TypeArgs) { + AddQualType(Arg); + } + + auto Protocols = T->getProtocols(); + ID.AddInteger(Protocols.size()); + for (auto Protocol : Protocols) { + AddDecl(Protocol); + } + + Hash.AddBoolean(T->isKindOfType()); + + VisitType(T); + } + + void VisitObjCInterfaceType(const ObjCInterfaceType *T) { + // This type is handled by the parent type ObjCObjectType. + VisitObjCObjectType(T); + } + + void VisitObjCTypeParamType(const ObjCTypeParamType *T) { + AddDecl(T->getDecl()); + auto Protocols = T->getProtocols(); + ID.AddInteger(Protocols.size()); + for (auto Protocol : Protocols) { + AddDecl(Protocol); + } + + VisitType(T); + } + + void VisitPackExpansionType(const PackExpansionType *T) { + AddQualType(T->getPattern()); + VisitType(T); + } + + void VisitParenType(const ParenType *T) { + AddQualType(T->getInnerType()); + VisitType(T); + } + + void VisitPipeType(const PipeType *T) { + AddQualType(T->getElementType()); + Hash.AddBoolean(T->isReadOnly()); + VisitType(T); + } + void VisitPointerType(const PointerType *T) { AddQualType(T->getPointeeType()); VisitType(T); @@ -744,6 +908,43 @@ public: VisitReferenceType(T); } + void + VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { + AddType(T->getReplacedParameter()); + Hash.AddTemplateArgument(T->getArgumentPack()); + VisitType(T); + } + + void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { + AddType(T->getReplacedParameter()); + AddQualType(T->getReplacementType()); + VisitType(T); + } + + void VisitTagType(const TagType *T) { + AddDecl(T->getDecl()); + VisitType(T); + } + + void VisitRecordType(const RecordType *T) { VisitTagType(T); } + void VisitEnumType(const EnumType *T) { VisitTagType(T); } + + void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { + ID.AddInteger(T->getNumArgs()); + for (const auto &TA : T->template_arguments()) { + Hash.AddTemplateArgument(TA); + } + Hash.AddTemplateName(T->getTemplateName()); + VisitType(T); + } + + void VisitTemplateTypeParmType(const TemplateTypeParmType *T) { + ID.AddInteger(T->getDepth()); + ID.AddInteger(T->getIndex()); + Hash.AddBoolean(T->isParameterPack()); + AddDecl(T->getDecl()); + } + void VisitTypedefType(const TypedefType *T) { AddDecl(T->getDecl()); QualType UnderlyingType = T->getDecl()->getUnderlyingType(); @@ -766,13 +967,18 @@ public: VisitType(T); } - void VisitTagType(const TagType *T) { - AddDecl(T->getDecl()); + void VisitTypeOfExprType(const TypeOfExprType *T) { + AddStmt(T->getUnderlyingExpr()); + Hash.AddBoolean(T->isSugared()); + if (T->isSugared()) + AddQualType(T->desugar()); + + VisitType(T); + } + void VisitTypeOfType(const TypeOfType *T) { + AddQualType(T->getUnderlyingType()); VisitType(T); } - - void VisitRecordType(const RecordType *T) { VisitTagType(T); } - void VisitEnumType(const EnumType *T) { VisitTagType(T); } void VisitTypeWithKeyword(const TypeWithKeyword *T) { ID.AddInteger(T->getKeyword()); @@ -802,20 +1008,26 @@ public: VisitTypeWithKeyword(T); } - void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { - ID.AddInteger(T->getNumArgs()); - for (const auto &TA : T->template_arguments()) { - Hash.AddTemplateArgument(TA); - } - Hash.AddTemplateName(T->getTemplateName()); + void VisitUnaryTransformType(const UnaryTransformType *T) { + AddQualType(T->getUnderlyingType()); + AddQualType(T->getBaseType()); VisitType(T); } - void VisitTemplateTypeParmType(const TemplateTypeParmType *T) { - ID.AddInteger(T->getDepth()); - ID.AddInteger(T->getIndex()); - Hash.AddBoolean(T->isParameterPack()); + void VisitUnresolvedUsingType(const UnresolvedUsingType *T) { AddDecl(T->getDecl()); + VisitType(T); + } + + void VisitVectorType(const VectorType *T) { + AddQualType(T->getElementType()); + ID.AddInteger(T->getNumElements()); + ID.AddInteger(T->getVectorKind()); + VisitType(T); + } + + void VisitExtVectorType(const ExtVectorType * T) { + VisitVectorType(T); } }; } // namespace diff --git a/lib/AST/OSLog.cpp b/lib/AST/OSLog.cpp new file mode 100644 index 000000000000..df2f808728cf --- /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 50729264bfe1..76098f15bf36 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" @@ -106,6 +107,11 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_from: 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; } @@ -175,12 +181,68 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_from: 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; } return nullptr; } +OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num, + unsigned NumLoops, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops)); + auto *Clause = + new (Mem) OMPOrderedClause(Num, NumLoops, StartLoc, LParenLoc, EndLoc); + for (unsigned I = 0; I < NumLoops; ++I) { + Clause->setLoopNumIterations(I, nullptr); + Clause->setLoopCounter(I, nullptr); + } + return Clause; +} + +OMPOrderedClause *OMPOrderedClause::CreateEmpty(const ASTContext &C, + unsigned NumLoops) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops)); + auto *Clause = new (Mem) OMPOrderedClause(NumLoops); + for (unsigned I = 0; I < NumLoops; ++I) { + Clause->setLoopNumIterations(I, nullptr); + Clause->setLoopCounter(I, nullptr); + } + return Clause; +} + +void OMPOrderedClause::setLoopNumIterations(unsigned NumLoop, + Expr *NumIterations) { + assert(NumLoop < NumberOfLoops && "out of loops number."); + getTrailingObjects<Expr *>()[NumLoop] = NumIterations; +} + +ArrayRef<Expr *> OMPOrderedClause::getLoopNumIterations() const { + return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumberOfLoops); +} + +void OMPOrderedClause::setLoopCounter(unsigned NumLoop, Expr *Counter) { + assert(NumLoop < NumberOfLoops && "out of loops number."); + getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop] = Counter; +} + +Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) { + assert(NumLoop < NumberOfLoops && "out of loops number."); + return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop]; +} + +const Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) const { + assert(NumLoop < NumberOfLoops && "out of loops number."); + return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop]; +} + void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { assert(VL.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); @@ -653,44 +715,58 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) { return new (Mem) OMPFlushClause(N); } -OMPDependClause *OMPDependClause::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, OpenMPDependClauseKind DepKind, - SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1)); - OMPDependClause *Clause = - new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size()); +OMPDependClause * +OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + OpenMPDependClauseKind DepKind, SourceLocation DepLoc, + SourceLocation ColonLoc, ArrayRef<Expr *> VL, + unsigned NumLoops) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops)); + OMPDependClause *Clause = new (Mem) + OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops); Clause->setVarRefs(VL); Clause->setDependencyKind(DepKind); Clause->setDependencyLoc(DepLoc); Clause->setColonLoc(ColonLoc); - Clause->setCounterValue(nullptr); + for (unsigned I = 0 ; I < NumLoops; ++I) + Clause->setLoopData(I, nullptr); return Clause; } -OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1)); - return new (Mem) OMPDependClause(N); +OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N, + unsigned NumLoops) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops)); + return new (Mem) OMPDependClause(N, NumLoops); } -void OMPDependClause::setCounterValue(Expr *V) { - assert(getDependencyKind() == OMPC_DEPEND_sink || - getDependencyKind() == OMPC_DEPEND_source || V == nullptr); - *getVarRefs().end() = V; +void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) { + assert((getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source) && + NumLoop < NumLoops && + "Expected sink or source depend + loop index must be less number of " + "loops."); + auto It = std::next(getVarRefs().end(), NumLoop); + *It = Cnt; } -const Expr *OMPDependClause::getCounterValue() const { - auto *V = *getVarRefs().end(); - assert(getDependencyKind() == OMPC_DEPEND_sink || - getDependencyKind() == OMPC_DEPEND_source || V == nullptr); - return V; +Expr *OMPDependClause::getLoopData(unsigned NumLoop) { + assert((getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source) && + NumLoop < NumLoops && + "Expected sink or source depend + loop index must be less number of " + "loops."); + auto It = std::next(getVarRefs().end(), NumLoop); + return *It; } -Expr *OMPDependClause::getCounterValue() { - auto *V = *getVarRefs().end(); - assert(getDependencyKind() == OMPC_DEPEND_sink || - getDependencyKind() == OMPC_DEPEND_source || V == nullptr); - return V; +const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const { + assert((getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source) && + NumLoop < NumLoops && + "Expected sink or source depend + loop index must be less number of " + "loops."); + auto It = std::next(getVarRefs().end(), NumLoop); + return *It; } unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber( @@ -720,8 +796,10 @@ OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, MappableExprComponentListsRef ComponentLists, - OpenMPMapClauseKind TypeModifier, OpenMPMapClauseKind Type, - bool TypeIsImplicit, SourceLocation TypeLoc) { + ArrayRef<OpenMPMapModifierKind> MapModifiers, + ArrayRef<SourceLocation> MapModifiersLoc, + OpenMPMapClauseKind Type, bool TypeIsImplicit, + SourceLocation TypeLoc) { unsigned NumVars = Vars.size(); unsigned NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); @@ -744,12 +822,12 @@ OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc, NumVars, NumUniqueDeclarations, NumUniqueDeclarations + NumComponentLists, NumComponents)); OMPMapClause *Clause = new (Mem) OMPMapClause( - TypeModifier, Type, TypeIsImplicit, TypeLoc, StartLoc, LParenLoc, EndLoc, - NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents); + MapModifiers, MapModifiersLoc, Type, TypeIsImplicit, TypeLoc, StartLoc, + LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, NumComponentLists, + NumComponents); Clause->setVarRefs(Vars); Clause->setClauseInfo(Declarations, ComponentLists); - Clause->setMapTypeModifier(TypeModifier); Clause->setMapType(Type); Clause->setMapLoc(TypeLoc); return Clause; @@ -976,3 +1054,444 @@ 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) { + for (unsigned I = 0; I < OMPMapClause::NumberOfModifiers; ++I) { + if (Node->getMapTypeModifier(I) != OMPC_MAP_MODIFIER_unknown) { + OS << getOpenMPSimpleClauseTypeName(OMPC_map, + Node->getMapTypeModifier(I)); + 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 af2a480dc23f..88c178aa372f 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 000000000000..e0a0c5b7582a --- /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 95da9ed6d238..ab873a396419 100644 --- a/lib/AST/RawCommentList.cpp +++ b/lib/AST/RawCommentList.cpp @@ -68,8 +68,8 @@ bool mergedCommentIsTrailingComment(StringRef Comment) { /// column. bool commentsStartOnSameColumn(const SourceManager &SM, const RawComment &R1, const RawComment &R2) { - SourceLocation L1 = R1.getLocStart(); - SourceLocation L2 = R2.getLocStart(); + SourceLocation L1 = R1.getBeginLoc(); + SourceLocation L2 = R2.getBeginLoc(); bool Invalid = false; unsigned C1 = SM.getPresumedColumnNumber(L1, &Invalid); if (!Invalid) { @@ -278,8 +278,8 @@ void RawCommentList::addComment(const RawComment &RC, // Check if the comments are not in source order. while (!Comments.empty() && - !SourceMgr.isBeforeInTranslationUnit(Comments.back()->getLocStart(), - RC.getLocStart())) { + !SourceMgr.isBeforeInTranslationUnit(Comments.back()->getBeginLoc(), + RC.getBeginLoc())) { // If they are, just pop a few last comments that don't fit. // This happens if an \#include directive contains comments. Comments.pop_back(); @@ -316,9 +316,9 @@ void RawCommentList::addComment(const RawComment &RC, (C1.isTrailingComment() && !C2.isTrailingComment() && isOrdinaryKind(C2.getKind()) && commentsStartOnSameColumn(SourceMgr, C1, C2))) && - onlyWhitespaceBetween(SourceMgr, C1.getLocEnd(), C2.getLocStart(), + onlyWhitespaceBetween(SourceMgr, C1.getEndLoc(), C2.getBeginLoc(), /*MaxNewlinesAllowed=*/1)) { - SourceRange MergedRange(C1.getLocStart(), C2.getLocEnd()); + SourceRange MergedRange(C1.getBeginLoc(), C2.getEndLoc()); *Comments.back() = RawComment(SourceMgr, MergedRange, CommentOpts, true); } else { Comments.push_back(new (Allocator) RawComment(RC)); @@ -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 6f71d5b83e62..62dc22c81403 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 000000000000..08ba7a7a4f5c --- /dev/null +++ b/lib/AST/ScanfFormatString.cpp @@ -0,0 +1,565 @@ +//= 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(); + } + llvm_unreachable("Unsupported LenghtModifier Type"); + + // 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(); + } + llvm_unreachable("Unsupported LenghtModifier Type"); + + // 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/SelectorLocationsKind.cpp b/lib/AST/SelectorLocationsKind.cpp index 671207a7f2d9..8b72c85d7ef7 100644 --- a/lib/AST/SelectorLocationsKind.cpp +++ b/lib/AST/SelectorLocationsKind.cpp @@ -49,12 +49,12 @@ SourceLocation getArgLoc(T* Arg); template <> SourceLocation getArgLoc<Expr>(Expr *Arg) { - return Arg->getLocStart(); + return Arg->getBeginLoc(); } template <> SourceLocation getArgLoc<ParmVarDecl>(ParmVarDecl *Arg) { - SourceLocation Loc = Arg->getLocStart(); + SourceLocation Loc = Arg->getBeginLoc(); if (Loc.isInvalid()) return Loc; // -1 to point to left paren of the method parameter's type. diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index a041006c905e..116291bfa1ef 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); @@ -113,17 +121,23 @@ void Stmt::EnableStatistics() { Stmt *Stmt::IgnoreImplicit() { Stmt *s = this; - if (auto *ewc = dyn_cast<ExprWithCleanups>(s)) - s = ewc->getSubExpr(); + Stmt *lasts = nullptr; + + while (s != lasts) { + lasts = s; - if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s)) - s = mte->GetTemporaryExpr(); + if (auto *fe = dyn_cast<FullExpr>(s)) + s = fe->getSubExpr(); - if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s)) - s = bte->getSubExpr(); + if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s)) + s = mte->GetTemporaryExpr(); - while (auto *ice = dyn_cast<ImplicitCastExpr>(s)) - s = ice->getSubExpr(); + if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s)) + s = bte->getSubExpr(); + + if (auto *ice = dyn_cast<ImplicitCastExpr>(s)) + s = ice->getSubExpr(); + } return s; } @@ -185,30 +199,26 @@ namespace { return bad(); } - typedef SourceLocation getLocStart_t() const; - template <class T> good implements_getLocStart(getLocStart_t T::*) { + typedef SourceLocation getBeginLoc_t() const; + template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) { return good(); } LLVM_ATTRIBUTE_UNUSED - static bad implements_getLocStart(getLocStart_t Stmt::*) { - return bad(); - } + static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); } typedef SourceLocation getLocEnd_t() const; - template <class T> good implements_getLocEnd(getLocEnd_t T::*) { + template <class T> good implements_getEndLoc(getLocEnd_t T::*) { return good(); } LLVM_ATTRIBUTE_UNUSED - static bad implements_getLocEnd(getLocEnd_t Stmt::*) { - return bad(); - } + static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); } #define ASSERT_IMPLEMENTS_children(type) \ (void) is_good(implements_children(&type::children)) -#define ASSERT_IMPLEMENTS_getLocStart(type) \ - (void) is_good(implements_getLocStart(&type::getLocStart)) -#define ASSERT_IMPLEMENTS_getLocEnd(type) \ - (void) is_good(implements_getLocEnd(&type::getLocEnd)) +#define ASSERT_IMPLEMENTS_getBeginLoc(type) \ + (void)is_good(implements_getBeginLoc(&type::getBeginLoc)) +#define ASSERT_IMPLEMENTS_getEndLoc(type) \ + (void)is_good(implements_getEndLoc(&type::getEndLoc)) } // namespace @@ -217,10 +227,10 @@ namespace { LLVM_ATTRIBUTE_UNUSED static inline void check_implementations() { #define ABSTRACT_STMT(type) -#define STMT(type, base) \ - ASSERT_IMPLEMENTS_children(type); \ - ASSERT_IMPLEMENTS_getLocStart(type); \ - ASSERT_IMPLEMENTS_getLocEnd(type); +#define STMT(type, base) \ + ASSERT_IMPLEMENTS_children(type); \ + ASSERT_IMPLEMENTS_getBeginLoc(type); \ + ASSERT_IMPLEMENTS_getEndLoc(type); #include "clang/AST/StmtNodes.inc" } @@ -257,8 +267,8 @@ namespace { template <class S> SourceRange getSourceRangeImpl(const Stmt *stmt, SourceRange (Stmt::*v)() const) { - return SourceRange(static_cast<const S*>(stmt)->getLocStart(), - static_cast<const S*>(stmt)->getLocEnd()); + return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(), + static_cast<const S *>(stmt)->getEndLoc()); } } // namespace @@ -275,36 +285,41 @@ SourceRange Stmt::getSourceRange() const { llvm_unreachable("unknown statement kind!"); } -SourceLocation Stmt::getLocStart() const { -// llvm::errs() << "getLocStart() for " << getStmtClassName() << "\n"; +SourceLocation Stmt::getBeginLoc() const { + // llvm::errs() << "getBeginLoc() for " << getStmtClassName() << "\n"; switch (getStmtClass()) { case Stmt::NoStmtClass: llvm_unreachable("statement without class"); #define ABSTRACT_STMT(type) -#define STMT(type, base) \ - case Stmt::type##Class: \ - return static_cast<const type*>(this)->getLocStart(); +#define STMT(type, base) \ + case Stmt::type##Class: \ + return static_cast<const type *>(this)->getBeginLoc(); #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind"); } -SourceLocation Stmt::getLocEnd() const { +SourceLocation Stmt::getEndLoc() const { switch (getStmtClass()) { case Stmt::NoStmtClass: llvm_unreachable("statement without class"); #define ABSTRACT_STMT(type) -#define STMT(type, base) \ - case Stmt::type##Class: \ - return static_cast<const type*>(this)->getLocEnd(); +#define STMT(type, base) \ + case Stmt::type##Class: \ + return static_cast<const type *>(this)->getEndLoc(); #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind"); } +int64_t Stmt::getID(const ASTContext &Context) const { + 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) { @@ -789,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; + + setCond(Cond); + setThen(Then); + if (HasElse) + setElse(Else); + if (HasVar) + setConditionVariable(Ctx, Var); + if (HasInit) + setInit(Init); + + setIfLoc(IL); + if (HasElse) + setElseLoc(EL); } -VarDecl *IfStmt::getConditionVariable() const { - if (!SubExprs[VAR]) - return nullptr; +IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit) + : Stmt(IfStmtClass, Empty) { + IfStmtBits.HasElse = HasElse; + IfStmtBits.HasVar = HasVar; + IfStmtBits.HasInit = HasInit; +} - auto *DS = cast<DeclStmt>(SubExprs[VAR]); +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; 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 { @@ -855,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); +} - auto *DS = cast<DeclStmt>(SubExprs[VAR]); +WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) { + void *Mem = + Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), + alignof(WhileStmt)); + return new (Mem) WhileStmt(EmptyShell(), HasVar); +} + +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 @@ -925,11 +1047,54 @@ LabelDecl *IndirectGotoStmt::getConstantTarget() { } // ReturnStmt -const Expr* ReturnStmt::getRetValue() const { - 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; } -Expr* ReturnStmt::getRetValue() { - return cast_or_null<Expr>(RetExpr); + +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/StmtCXX.cpp b/lib/AST/StmtCXX.cpp index bf2d6a16fb5f..12367f8fd54b 100644 --- a/lib/AST/StmtCXX.cpp +++ b/lib/AST/StmtCXX.cpp @@ -45,7 +45,7 @@ CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, std::copy(handlers.begin(), handlers.end(), Stmts + 1); } -CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, +CXXForRangeStmt::CXXForRangeStmt(Stmt *Init, DeclStmt *Range, DeclStmt *BeginStmt, DeclStmt *EndStmt, Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, SourceLocation FL, @@ -53,6 +53,7 @@ CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, SourceLocation RPL) : Stmt(CXXForRangeStmtClass), ForLoc(FL), CoawaitLoc(CAL), ColonLoc(CL), RParenLoc(RPL) { + SubExprs[INIT] = Init; SubExprs[RANGE] = Range; SubExprs[BEGINSTMT] = BeginStmt; SubExprs[ENDSTMT] = EndStmt; diff --git a/lib/AST/StmtObjC.cpp b/lib/AST/StmtObjC.cpp index eea03f64c2fe..ed21e2d0d2b6 100644 --- a/lib/AST/StmtObjC.cpp +++ b/lib/AST/StmtObjC.cpp @@ -64,10 +64,10 @@ ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context, return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); } -SourceLocation ObjCAtTryStmt::getLocEnd() const { +SourceLocation ObjCAtTryStmt::getEndLoc() const { if (HasFinally) - return getFinallyStmt()->getLocEnd(); + return getFinallyStmt()->getEndLoc(); if (NumCatchStmts) - return getCatchStmt(NumCatchStmts - 1)->getLocEnd(); - return getTryBody()->getLocEnd(); + return getCatchStmt(NumCatchStmts - 1)->getEndLoc(); + return getTryBody()->getEndLoc(); } diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp index 1258af7a2d37..85a2daa0801a 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 cbf26c036058..ae726e387107 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -69,14 +69,16 @@ namespace { unsigned IndentLevel; PrinterHelper* Helper; PrintingPolicy Policy; + std::string NL; const ASTContext *Context; public: StmtPrinter(raw_ostream &os, PrinterHelper *helper, const PrintingPolicy &Policy, unsigned Indentation = 0, + StringRef NL = "\n", const ASTContext *Context = nullptr) : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy), - Context(Context) {} + NL(NL), Context(Context) {} void PrintStmt(Stmt *S) { PrintStmt(S, Policy.Indentation); @@ -88,15 +90,37 @@ namespace { // If this is an expr used in a stmt context, indent and newline it. Indent(); Visit(S); - OS << ";\n"; + OS << ";" << NL; } else if (S) { Visit(S); } else { - Indent() << "<<<NULL STATEMENT>>>\n"; + Indent() << "<<<NULL STATEMENT>>>" << NL; } IndentLevel -= SubIndent; } + void PrintInitStmt(Stmt *S, unsigned PrefixWidth) { + // FIXME: Cope better with odd prefix widths. + IndentLevel += (PrefixWidth + 1) / 2; + if (auto *DS = dyn_cast<DeclStmt>(S)) + PrintRawDeclStmt(DS); + else + PrintExpr(cast<Expr>(S)); + OS << "; "; + IndentLevel -= (PrefixWidth + 1) / 2; + } + + void PrintControlledStmt(Stmt *S) { + if (auto *CS = dyn_cast<CompoundStmt>(S)) { + OS << " "; + PrintRawCompoundStmt(CS); + OS << NL; + } else { + OS << NL; + PrintStmt(S); + } + } + void PrintRawCompoundStmt(CompoundStmt *S); void PrintRawDecl(Decl *D); void PrintRawDeclStmt(const DeclStmt *S); @@ -128,7 +152,7 @@ namespace { } void VisitStmt(Stmt *Node) LLVM_ATTRIBUTE_UNUSED { - Indent() << "<<unknown stmt type>>\n"; + Indent() << "<<unknown stmt type>>" << NL; } void VisitExpr(Expr *Node) LLVM_ATTRIBUTE_UNUSED { @@ -152,7 +176,7 @@ namespace { /// PrintRawCompoundStmt - Print a compound stmt without indenting the {, and /// with no newline after the }. void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) { - OS << "{\n"; + OS << "{" << NL; for (auto *I : Node->body()) PrintStmt(I); @@ -169,19 +193,19 @@ void StmtPrinter::PrintRawDeclStmt(const DeclStmt *S) { } void StmtPrinter::VisitNullStmt(NullStmt *Node) { - Indent() << ";\n"; + Indent() << ";" << NL; } void StmtPrinter::VisitDeclStmt(DeclStmt *Node) { Indent(); PrintRawDeclStmt(Node); - OS << ";\n"; + OS << ";" << NL; } void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) { Indent(); PrintRawCompoundStmt(Node); - OS << "\n"; + OS << "" << NL; } void StmtPrinter::VisitCaseStmt(CaseStmt *Node) { @@ -191,18 +215,18 @@ void StmtPrinter::VisitCaseStmt(CaseStmt *Node) { OS << " ... "; PrintExpr(Node->getRHS()); } - OS << ":\n"; + OS << ":" << NL; PrintStmt(Node->getSubStmt(), 0); } void StmtPrinter::VisitDefaultStmt(DefaultStmt *Node) { - Indent(-1) << "default:\n"; + Indent(-1) << "default:" << NL; PrintStmt(Node->getSubStmt(), 0); } void StmtPrinter::VisitLabelStmt(LabelStmt *Node) { - Indent(-1) << Node->getName() << ":\n"; + Indent(-1) << Node->getName() << ":" << NL; PrintStmt(Node->getSubStmt(), 0); } @@ -216,6 +240,8 @@ void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) { void StmtPrinter::PrintRawIfStmt(IfStmt *If) { OS << "if ("; + if (If->getInit()) + PrintInitStmt(If->getInit(), 4); if (const DeclStmt *DS = If->getConditionVariableDeclStmt()) PrintRawDeclStmt(DS); else @@ -225,9 +251,9 @@ void StmtPrinter::PrintRawIfStmt(IfStmt *If) { if (auto *CS = dyn_cast<CompoundStmt>(If->getThen())) { OS << ' '; PrintRawCompoundStmt(CS); - OS << (If->getElse() ? ' ' : '\n'); + OS << (If->getElse() ? " " : NL); } else { - OS << '\n'; + OS << NL; PrintStmt(If->getThen()); if (If->getElse()) Indent(); } @@ -238,12 +264,12 @@ void StmtPrinter::PrintRawIfStmt(IfStmt *If) { if (auto *CS = dyn_cast<CompoundStmt>(Else)) { OS << ' '; PrintRawCompoundStmt(CS); - OS << '\n'; + OS << NL; } else if (auto *ElseIf = dyn_cast<IfStmt>(Else)) { OS << ' '; PrintRawIfStmt(ElseIf); } else { - OS << '\n'; + OS << NL; PrintStmt(If->getElse()); } } @@ -256,21 +282,14 @@ void StmtPrinter::VisitIfStmt(IfStmt *If) { void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) { Indent() << "switch ("; + if (Node->getInit()) + PrintInitStmt(Node->getInit(), 8); if (const DeclStmt *DS = Node->getConditionVariableDeclStmt()) PrintRawDeclStmt(DS); else PrintExpr(Node->getCond()); OS << ")"; - - // Pretty print compoundstmt bodies (very common). - if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) { - OS << " "; - PrintRawCompoundStmt(CS); - OS << "\n"; - } else { - OS << "\n"; - PrintStmt(Node->getBody()); - } + PrintControlledStmt(Node->getBody()); } void StmtPrinter::VisitWhileStmt(WhileStmt *Node) { @@ -279,7 +298,7 @@ void StmtPrinter::VisitWhileStmt(WhileStmt *Node) { PrintRawDeclStmt(DS); else PrintExpr(Node->getCond()); - OS << ")\n"; + OS << ")" << NL; PrintStmt(Node->getBody()); } @@ -289,43 +308,31 @@ void StmtPrinter::VisitDoStmt(DoStmt *Node) { PrintRawCompoundStmt(CS); OS << " "; } else { - OS << "\n"; + OS << NL; PrintStmt(Node->getBody()); Indent(); } OS << "while ("; PrintExpr(Node->getCond()); - OS << ");\n"; + OS << ");" << NL; } void StmtPrinter::VisitForStmt(ForStmt *Node) { Indent() << "for ("; - if (Node->getInit()) { - if (auto *DS = dyn_cast<DeclStmt>(Node->getInit())) - PrintRawDeclStmt(DS); - else - PrintExpr(cast<Expr>(Node->getInit())); - } - OS << ";"; - if (Node->getCond()) { - OS << " "; + if (Node->getInit()) + PrintInitStmt(Node->getInit(), 5); + else + OS << (Node->getCond() ? "; " : ";"); + if (Node->getCond()) PrintExpr(Node->getCond()); - } OS << ";"; if (Node->getInc()) { OS << " "; PrintExpr(Node->getInc()); } - OS << ") "; - - if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) { - PrintRawCompoundStmt(CS); - OS << "\n"; - } else { - OS << "\n"; - PrintStmt(Node->getBody()); - } + OS << ")"; + PrintControlledStmt(Node->getBody()); } void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) { @@ -336,28 +343,21 @@ void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) { PrintExpr(cast<Expr>(Node->getElement())); OS << " in "; PrintExpr(Node->getCollection()); - OS << ") "; - - if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) { - PrintRawCompoundStmt(CS); - OS << "\n"; - } else { - OS << "\n"; - PrintStmt(Node->getBody()); - } + OS << ")"; + PrintControlledStmt(Node->getBody()); } void StmtPrinter::VisitCXXForRangeStmt(CXXForRangeStmt *Node) { Indent() << "for ("; + if (Node->getInit()) + PrintInitStmt(Node->getInit(), 5); PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressInitializers = true; Node->getLoopVariable()->print(OS, SubPolicy, IndentLevel); OS << " : "; PrintExpr(Node->getRangeInit()); - OS << ") {\n"; - PrintStmt(Node->getBody()); - Indent() << "}"; - if (Policy.IncludeNewlines) OS << "\n"; + OS << ")"; + PrintControlledStmt(Node->getBody()); } void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) { @@ -378,24 +378,24 @@ void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) { void StmtPrinter::VisitGotoStmt(GotoStmt *Node) { Indent() << "goto " << Node->getLabel()->getName() << ";"; - if (Policy.IncludeNewlines) OS << "\n"; + if (Policy.IncludeNewlines) OS << NL; } void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) { Indent() << "goto *"; PrintExpr(Node->getTarget()); OS << ";"; - if (Policy.IncludeNewlines) OS << "\n"; + if (Policy.IncludeNewlines) OS << NL; } void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) { Indent() << "continue;"; - if (Policy.IncludeNewlines) OS << "\n"; + if (Policy.IncludeNewlines) OS << NL; } void StmtPrinter::VisitBreakStmt(BreakStmt *Node) { Indent() << "break;"; - if (Policy.IncludeNewlines) OS << "\n"; + if (Policy.IncludeNewlines) OS << NL; } void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) { @@ -405,7 +405,7 @@ void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) { PrintExpr(Node->getRetValue()); } OS << ";"; - if (Policy.IncludeNewlines) OS << "\n"; + if (Policy.IncludeNewlines) OS << NL; } void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { @@ -470,17 +470,17 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { } OS << ");"; - if (Policy.IncludeNewlines) OS << "\n"; + if (Policy.IncludeNewlines) OS << NL; } void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) { // FIXME: Implement MS style inline asm statement printer. Indent() << "__asm "; if (Node->hasBraces()) - OS << "{\n"; - OS << Node->getAsmString() << "\n"; + OS << "{" << NL; + OS << Node->getAsmString() << NL; if (Node->hasBraces()) - Indent() << "}\n"; + Indent() << "}" << NL; } void StmtPrinter::VisitCapturedStmt(CapturedStmt *Node) { @@ -491,7 +491,7 @@ void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) { Indent() << "@try"; if (auto *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) { PrintRawCompoundStmt(TS); - OS << "\n"; + OS << NL; } for (unsigned I = 0, N = Node->getNumCatchStmts(); I != N; ++I) { @@ -504,14 +504,14 @@ void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) { OS << ")"; if (auto *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody())) { PrintRawCompoundStmt(CS); - OS << "\n"; + OS << NL; } } if (auto *FS = static_cast<ObjCAtFinallyStmt *>(Node->getFinallyStmt())) { Indent() << "@finally"; PrintRawCompoundStmt(dyn_cast<CompoundStmt>(FS->getFinallyBody())); - OS << "\n"; + OS << NL; } } @@ -519,7 +519,7 @@ void StmtPrinter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Node) { } void StmtPrinter::VisitObjCAtCatchStmt (ObjCAtCatchStmt *Node) { - Indent() << "@catch (...) { /* todo */ } \n"; + Indent() << "@catch (...) { /* todo */ } " << NL; } void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) { @@ -528,7 +528,7 @@ void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) { OS << " "; PrintExpr(Node->getThrowExpr()); } - OS << ";\n"; + OS << ";" << NL; } void StmtPrinter::VisitObjCAvailabilityCheckExpr( @@ -541,13 +541,13 @@ void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) { PrintExpr(Node->getSynchExpr()); OS << ")"; PrintRawCompoundStmt(Node->getSynchBody()); - OS << "\n"; + OS << NL; } void StmtPrinter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *Node) { Indent() << "@autoreleasepool"; PrintRawCompoundStmt(dyn_cast<CompoundStmt>(Node->getSubStmt())); - OS << "\n"; + OS << NL; } void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) { @@ -563,7 +563,7 @@ void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) { void StmtPrinter::VisitCXXCatchStmt(CXXCatchStmt *Node) { Indent(); PrintRawCXXCatchStmt(Node); - OS << "\n"; + OS << NL; } void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) { @@ -573,7 +573,7 @@ void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) { OS << " "; PrintRawCXXCatchStmt(Node->getHandler(i)); } - OS << "\n"; + OS << NL; } void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) { @@ -587,471 +587,38 @@ void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) { assert(F && "Must have a finally block..."); PrintRawSEHFinallyStmt(F); } - OS << "\n"; + OS << NL; } void StmtPrinter::PrintRawSEHFinallyStmt(SEHFinallyStmt *Node) { OS << "__finally "; PrintRawCompoundStmt(Node->getBlock()); - OS << "\n"; + OS << NL; } void StmtPrinter::PrintRawSEHExceptHandler(SEHExceptStmt *Node) { OS << "__except ("; VisitExpr(Node->getFilterExpr()); - OS << ")\n"; + OS << ")" << NL; PrintRawCompoundStmt(Node->getBlock()); - OS << "\n"; + OS << NL; } void StmtPrinter::VisitSEHExceptStmt(SEHExceptStmt *Node) { Indent(); PrintRawSEHExceptHandler(Node); - OS << "\n"; + OS << NL; } void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) { Indent(); PrintRawSEHFinallyStmt(Node); - OS << "\n"; + OS << NL; } void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) { Indent() << "__leave;"; - if (Policy.IncludeNewlines) OS << "\n"; -} - -//===----------------------------------------------------------------------===// -// 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::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 << ")"; - } + if (Policy.IncludeNewlines) OS << NL; } //===----------------------------------------------------------------------===// @@ -1067,7 +634,7 @@ void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S, OS << ' '; Printer.Visit(Clause); } - OS << "\n"; + OS << NL; if (!ForceNoStmt && S->hasAssociatedStmt()) PrintStmt(S->getInnermostCapturedStmt()->getCapturedStmt()); } @@ -1339,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); @@ -1378,7 +949,7 @@ static bool isImplicitSelf(const Expr *E) { if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) { if (const auto *PD = dyn_cast<ImplicitParamDecl>(DRE->getDecl())) { if (PD->getParameterKind() == ImplicitParamDecl::ObjCSelf && - DRE->getLocStart().isInvalid()) + DRE->getBeginLoc().isInvalid()) return true; } } @@ -1424,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) { @@ -1668,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; @@ -2808,8 +2382,9 @@ void Stmt::dumpPretty(const ASTContext &Context) const { void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation, + StringRef NL, const ASTContext *Context) const { - StmtPrinter P(OS, Helper, Policy, Indentation, Context); + StmtPrinter P(OS, Helper, Policy, Indentation, NL, Context); P.Visit(const_cast<Stmt*>(this)); } diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 15653c4fd838..ec4dac03d497 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -189,7 +189,7 @@ namespace { // store its nullness. Add a boolean here to match. ID.AddBoolean(true); } - Hash.AddDeclarationName(Name); + Hash.AddDeclarationName(Name, TreatAsDecl); } void VisitIdentifierInfo(IdentifierInfo *II) override { ID.AddBoolean(II); @@ -467,6 +467,21 @@ void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { } 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()) @@ -984,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) @@ -998,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 000000000000..b51a9006226a --- /dev/null +++ b/lib/AST/TextNodeDumper.cpp @@ -0,0 +1,1168 @@ +//===--- 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" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclOpenMP.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/LocInfoType.h" + +using namespace clang; + +static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {} + +template <typename T> +static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) { + const T *First = D->getFirstDecl(); + if (First != D) + OS << " first " << First; +} + +template <typename T> +static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) { + const T *Prev = D->getPreviousDecl(); + if (Prev) + OS << " prev " << Prev; +} + +/// Dump the previous declaration in the redeclaration chain for a declaration, +/// if any. +static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) { + switch (D->getKind()) { +#define DECL(DERIVED, BASE) \ + case Decl::DERIVED: \ + return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D)); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" + } + llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); +} + +TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors, + const SourceManager *SM, + const PrintingPolicy &PrintPolicy, + const comments::CommandTraits *Traits) + : TextTreeStructure(OS, ShowColors), 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::Visit(const Attr *A) { + { + ColorScope Color(OS, ShowColors, AttrColor); + + switch (A->getKind()) { +#define ATTR(X) \ + case attr::X: \ + OS << #X; \ + break; +#include "clang/Basic/AttrList.inc" + } + OS << "Attr"; + } + dumpPointer(A); + dumpSourceRange(A->getRange()); + if (A->isInherited()) + OS << " Inherited"; + if (A->isImplicit()) + OS << " Implicit"; + + ConstAttrVisitor<TextNodeDumper>::Visit(A); +} + +void TextNodeDumper::Visit(const TemplateArgument &TA, SourceRange R, + const Decl *From, StringRef Label) { + OS << "TemplateArgument"; + if (R.isValid()) + dumpSourceRange(R); + + if (From) + dumpDeclRef(From, Label); + + ConstTemplateArgumentVisitor<TextNodeDumper>::Visit(TA); +} + +void TextNodeDumper::Visit(const Stmt *Node) { + if (!Node) { + ColorScope Color(OS, ShowColors, NullColor); + OS << "<<<NULL>>>"; + return; + } + { + ColorScope Color(OS, ShowColors, StmtColor); + OS << Node->getStmtClassName(); + } + dumpPointer(Node); + dumpSourceRange(Node->getSourceRange()); + + if (const auto *E = dyn_cast<Expr>(Node)) { + 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<TextNodeDumper>::Visit(Node); +} + +void TextNodeDumper::Visit(const Type *T) { + if (!T) { + ColorScope Color(OS, ShowColors, NullColor); + OS << "<<<NULL>>>"; + return; + } + if (isa<LocInfoType>(T)) { + { + ColorScope Color(OS, ShowColors, TypeColor); + OS << "LocInfo Type"; + } + dumpPointer(T); + return; + } + + { + ColorScope Color(OS, ShowColors, TypeColor); + OS << T->getTypeClassName() << "Type"; + } + dumpPointer(T); + OS << " "; + dumpBareType(QualType(T, 0), false); + + QualType SingleStepDesugar = + T->getLocallyUnqualifiedSingleStepDesugaredType(); + if (SingleStepDesugar != QualType(T, 0)) + OS << " sugar"; + + if (T->isDependentType()) + OS << " dependent"; + else if (T->isInstantiationDependentType()) + OS << " instantiation_dependent"; + + if (T->isVariablyModifiedType()) + OS << " variably_modified"; + if (T->containsUnexpandedParameterPack()) + OS << " contains_unexpanded_pack"; + if (T->isFromAST()) + OS << " imported"; + + TypeVisitor<TextNodeDumper>::Visit(T); +} + +void TextNodeDumper::Visit(QualType T) { + OS << "QualType"; + dumpPointer(T.getAsOpaquePtr()); + OS << " "; + dumpBareType(T, false); + OS << " " << T.split().Quals.getAsString(); +} + +void TextNodeDumper::Visit(const Decl *D) { + if (!D) { + ColorScope Color(OS, ShowColors, NullColor); + OS << "<<<NULL>>>"; + return; + } + + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << D->getDeclKindName() << "Decl"; + } + dumpPointer(D); + if (D->getLexicalDeclContext() != D->getDeclContext()) + OS << " parent " << cast<Decl>(D->getDeclContext()); + dumpPreviousDecl(OS, D); + dumpSourceRange(D->getSourceRange()); + OS << ' '; + dumpLocation(D->getLocation()); + if (D->isFromASTFile()) + OS << " imported"; + if (Module *M = D->getOwningModule()) + OS << " in " << M->getFullModuleName(); + if (auto *ND = dyn_cast<NamedDecl>(D)) + for (Module *M : D->getASTContext().getModulesWithMergedDefinition( + const_cast<NamedDecl *>(ND))) + AddChild([=] { OS << "also in " << M->getFullModuleName(); }); + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) + if (ND->isHidden()) + OS << " hidden"; + if (D->isImplicit()) + OS << " implicit"; + + if (D->isUsed()) + OS << " used"; + else if (D->isThisDeclarationReferenced()) + OS << " referenced"; + + if (D->isInvalidDecl()) + OS << " invalid"; + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isConstexpr()) + OS << " constexpr"; +} + +void TextNodeDumper::Visit(const CXXCtorInitializer *Init) { + OS << "CXXCtorInitializer"; + if (Init->isAnyMemberInitializer()) { + OS << ' '; + dumpBareDeclRef(Init->getAnyMember()); + } else if (Init->isBaseInitializer()) { + dumpType(QualType(Init->getBaseClass(), 0)); + } else if (Init->isDelegatingInitializer()) { + dumpType(Init->getTypeSourceInfo()->getType()); + } else { + llvm_unreachable("Unknown initializer type"); + } +} + +void TextNodeDumper::Visit(const BlockDecl::Capture &C) { + OS << "capture"; + if (C.isByRef()) + OS << " byref"; + if (C.isNested()) + OS << " nested"; + if (C.getVariable()) { + OS << ' '; + dumpBareDeclRef(C.getVariable()); + } +} + +void TextNodeDumper::Visit(const OMPClause *C) { + if (!C) { + ColorScope Color(OS, ShowColors, NullColor); + OS << "<<<NULL>>> OMPClause"; + return; + } + { + 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())); + if (C->isImplicit()) + OS << " <implicit>"; +} + +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 << ")"; +} + +void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) { + if (!D) + return; + + AddChild([=] { + if (!Label.empty()) + OS << Label << ' '; + dumpBareDeclRef(D); + }); +} + +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() << "\""; +} + +void TextNodeDumper::VisitNullTemplateArgument(const TemplateArgument &) { + OS << " null"; +} + +void TextNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) { + OS << " type"; + dumpType(TA.getAsType()); +} + +void TextNodeDumper::VisitDeclarationTemplateArgument( + const TemplateArgument &TA) { + OS << " decl"; + dumpDeclRef(TA.getAsDecl()); +} + +void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &) { + OS << " nullptr"; +} + +void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) { + OS << " integral " << TA.getAsIntegral(); +} + +void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) { + OS << " template "; + TA.getAsTemplate().dump(OS); +} + +void TextNodeDumper::VisitTemplateExpansionTemplateArgument( + const TemplateArgument &TA) { + OS << " template expansion "; + TA.getAsTemplateOrTemplatePattern().dump(OS); +} + +void TextNodeDumper::VisitExpressionTemplateArgument(const TemplateArgument &) { + OS << " expr"; +} + +void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &) { + OS << " pack"; +} + +static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { + if (Node->path_empty()) + return; + + OS << " ("; + bool First = true; + for (CastExpr::path_const_iterator I = Node->path_begin(), + E = Node->path_end(); + I != E; ++I) { + const CXXBaseSpecifier *Base = *I; + if (!First) + OS << " -> "; + + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + if (Base->isVirtual()) + OS << "virtual "; + OS << RD->getName(); + First = false; + } + + OS << ')'; +} + +void TextNodeDumper::VisitIfStmt(const IfStmt *Node) { + if (Node->hasInitStorage()) + OS << " has_init"; + if (Node->hasVarStorage()) + OS << " has_var"; + if (Node->hasElseStorage()) + OS << " has_else"; +} + +void TextNodeDumper::VisitSwitchStmt(const SwitchStmt *Node) { + if (Node->hasInitStorage()) + OS << " has_init"; + if (Node->hasVarStorage()) + OS << " has_var"; +} + +void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) { + if (Node->hasVarStorage()) + OS << " has_var"; +} + +void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) { + OS << " '" << Node->getName() << "'"; +} + +void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) { + OS << " '" << Node->getLabel()->getName() << "'"; + dumpPointer(Node->getLabel()); +} + +void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) { + if (Node->caseStmtIsGNURange()) + OS << " gnu_range"; +} + +void TextNodeDumper::VisitCallExpr(const CallExpr *Node) { + if (Node->usesADL()) + OS << " adl"; +} + +void TextNodeDumper::VisitCastExpr(const CastExpr *Node) { + OS << " <"; + { + ColorScope Color(OS, ShowColors, CastColor); + OS << Node->getCastKindName(); + } + dumpBasePath(OS, Node); + OS << ">"; +} + +void TextNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) { + VisitCastExpr(Node); + if (Node->isPartOfExplicitCast()) + OS << " part_of_explicit_cast"; +} + +void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { + OS << " "; + dumpBareDeclRef(Node->getDecl()); + if (Node->getDecl() != Node->getFoundDecl()) { + OS << " ("; + dumpBareDeclRef(Node->getFoundDecl()); + OS << ")"; + } +} + +void TextNodeDumper::VisitUnresolvedLookupExpr( + const UnresolvedLookupExpr *Node) { + OS << " ("; + if (!Node->requiresADL()) + OS << "no "; + OS << "ADL) = '" << Node->getName() << '\''; + + UnresolvedLookupExpr::decls_iterator I = Node->decls_begin(), + E = Node->decls_end(); + if (I == E) + OS << " empty"; + for (; I != E; ++I) + dumpPointer(*I); +} + +void TextNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << " " << Node->getDecl()->getDeclKindName() << "Decl"; + } + OS << "='" << *Node->getDecl() << "'"; + dumpPointer(Node->getDecl()); + if (Node->isFreeIvar()) + OS << " isFreeIvar"; +} + +void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { + OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind()); +} + +void TextNodeDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { + ColorScope Color(OS, ShowColors, ValueColor); + OS << " " << Node->getValue(); +} + +void TextNodeDumper::VisitIntegerLiteral(const IntegerLiteral *Node) { + bool isSigned = Node->getType()->isSignedIntegerType(); + ColorScope Color(OS, ShowColors, ValueColor); + OS << " " << Node->getValue().toString(10, isSigned); +} + +void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) { + ColorScope Color(OS, ShowColors, ValueColor); + OS << " " << Node->getValueAsString(/*Radix=*/10); +} + +void TextNodeDumper::VisitFloatingLiteral(const FloatingLiteral *Node) { + ColorScope Color(OS, ShowColors, ValueColor); + OS << " " << Node->getValueAsApproximateDouble(); +} + +void TextNodeDumper::VisitStringLiteral(const StringLiteral *Str) { + ColorScope Color(OS, ShowColors, ValueColor); + OS << " "; + Str->outputString(OS); +} + +void TextNodeDumper::VisitInitListExpr(const InitListExpr *ILE) { + if (auto *Field = ILE->getInitializedFieldInUnion()) { + OS << " field "; + dumpBareDeclRef(Field); + } +} + +void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) { + OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '" + << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; + if (!Node->canOverflow()) + OS << " cannot overflow"; +} + +void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr *Node) { + switch (Node->getKind()) { + case UETT_SizeOf: + OS << " sizeof"; + break; + case UETT_AlignOf: + OS << " alignof"; + break; + case UETT_VecStep: + OS << " vec_step"; + break; + case UETT_OpenMPRequiredSimdAlign: + OS << " __builtin_omp_required_simd_align"; + break; + case UETT_PreferredAlignOf: + OS << " __alignof"; + break; + } + if (Node->isArgumentType()) + dumpType(Node->getArgumentType()); +} + +void TextNodeDumper::VisitMemberExpr(const MemberExpr *Node) { + OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl(); + dumpPointer(Node->getMemberDecl()); +} + +void TextNodeDumper::VisitExtVectorElementExpr( + const ExtVectorElementExpr *Node) { + OS << " " << Node->getAccessor().getNameStart(); +} + +void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) { + OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; +} + +void TextNodeDumper::VisitCompoundAssignOperator( + const CompoundAssignOperator *Node) { + OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) + << "' ComputeLHSTy="; + dumpBareType(Node->getComputationLHSType()); + OS << " ComputeResultTy="; + dumpBareType(Node->getComputationResultType()); +} + +void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { + OS << " " << Node->getLabel()->getName(); + dumpPointer(Node->getLabel()); +} + +void TextNodeDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) { + OS << " " << Node->getCastName() << "<" + << Node->getTypeAsWritten().getAsString() << ">" + << " <" << Node->getCastKindName(); + dumpBasePath(OS, Node); + OS << ">"; +} + +void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) { + OS << " " << (Node->getValue() ? "true" : "false"); +} + +void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) { + OS << " this"; +} + +void TextNodeDumper::VisitCXXFunctionalCastExpr( + const CXXFunctionalCastExpr *Node) { + OS << " functional cast to " << Node->getTypeAsWritten().getAsString() << " <" + << Node->getCastKindName() << ">"; +} + +void TextNodeDumper::VisitCXXUnresolvedConstructExpr( + const CXXUnresolvedConstructExpr *Node) { + dumpType(Node->getTypeAsWritten()); + if (Node->isListInitialization()) + OS << " list"; +} + +void TextNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { + CXXConstructorDecl *Ctor = Node->getConstructor(); + dumpType(Ctor->getType()); + if (Node->isElidable()) + OS << " elidable"; + if (Node->isListInitialization()) + OS << " list"; + if (Node->isStdInitListInitialization()) + OS << " std::initializer_list"; + if (Node->requiresZeroInitialization()) + OS << " zeroing"; +} + +void TextNodeDumper::VisitCXXBindTemporaryExpr( + const CXXBindTemporaryExpr *Node) { + OS << " "; + dumpCXXTemporary(Node->getTemporary()); +} + +void TextNodeDumper::VisitCXXNewExpr(const CXXNewExpr *Node) { + if (Node->isGlobalNew()) + OS << " global"; + if (Node->isArray()) + OS << " array"; + if (Node->getOperatorNew()) { + OS << ' '; + dumpBareDeclRef(Node->getOperatorNew()); + } + // We could dump the deallocation function used in case of error, but it's + // usually not that interesting. +} + +void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) { + if (Node->isGlobalDelete()) + OS << " global"; + if (Node->isArrayForm()) + OS << " array"; + if (Node->getOperatorDelete()) { + OS << ' '; + dumpBareDeclRef(Node->getOperatorDelete()); + } +} + +void TextNodeDumper::VisitMaterializeTemporaryExpr( + const MaterializeTemporaryExpr *Node) { + if (const ValueDecl *VD = Node->getExtendingDecl()) { + OS << " extended by "; + dumpBareDeclRef(VD); + } +} + +void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) { + for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) + dumpDeclRef(Node->getObject(i), "cleanup"); +} + +void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { + dumpPointer(Node->getPack()); + dumpName(Node->getPack()); +} + +void TextNodeDumper::VisitCXXDependentScopeMemberExpr( + const CXXDependentScopeMemberExpr *Node) { + OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember(); +} + +void TextNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { + OS << " selector="; + Node->getSelector().print(OS); + switch (Node->getReceiverKind()) { + case ObjCMessageExpr::Instance: + break; + + case ObjCMessageExpr::Class: + OS << " class="; + dumpBareType(Node->getClassReceiver()); + break; + + case ObjCMessageExpr::SuperInstance: + OS << " super (instance)"; + break; + + case ObjCMessageExpr::SuperClass: + OS << " super (class)"; + break; + } +} + +void TextNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { + if (auto *BoxingMethod = Node->getBoxingMethod()) { + OS << " selector="; + BoxingMethod->getSelector().print(OS); + } +} + +void TextNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { + if (!Node->getCatchParamDecl()) + OS << " catch all"; +} + +void TextNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) { + dumpType(Node->getEncodedType()); +} + +void TextNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) { + OS << " "; + Node->getSelector().print(OS); +} + +void TextNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) { + OS << ' ' << *Node->getProtocol(); +} + +void TextNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) { + if (Node->isImplicitProperty()) { + OS << " Kind=MethodRef Getter=\""; + if (Node->getImplicitPropertyGetter()) + Node->getImplicitPropertyGetter()->getSelector().print(OS); + else + OS << "(null)"; + + OS << "\" Setter=\""; + if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) + Setter->getSelector().print(OS); + else + OS << "(null)"; + OS << "\""; + } else { + OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() + << '"'; + } + + if (Node->isSuperReceiver()) + OS << " super"; + + OS << " Messaging="; + if (Node->isMessagingGetter() && Node->isMessagingSetter()) + OS << "Getter&Setter"; + else if (Node->isMessagingGetter()) + OS << "Getter"; + else if (Node->isMessagingSetter()) + OS << "Setter"; +} + +void TextNodeDumper::VisitObjCSubscriptRefExpr( + const ObjCSubscriptRefExpr *Node) { + if (Node->isArraySubscriptRefExpr()) + OS << " Kind=ArraySubscript GetterForArray=\""; + else + OS << " Kind=DictionarySubscript GetterForDictionary=\""; + if (Node->getAtIndexMethodDecl()) + Node->getAtIndexMethodDecl()->getSelector().print(OS); + else + OS << "(null)"; + + if (Node->isArraySubscriptRefExpr()) + OS << "\" SetterForArray=\""; + else + OS << "\" SetterForDictionary=\""; + if (Node->setAtIndexMethodDecl()) + Node->setAtIndexMethodDecl()->getSelector().print(OS); + else + OS << "(null)"; +} + +void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) { + OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); +} + +void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) { + if (T->isSpelledAsLValue()) + OS << " written as lvalue reference"; +} + +void TextNodeDumper::VisitArrayType(const ArrayType *T) { + switch (T->getSizeModifier()) { + case ArrayType::Normal: + break; + case ArrayType::Static: + OS << " static"; + break; + case ArrayType::Star: + OS << " *"; + break; + } + OS << " " << T->getIndexTypeQualifiers().getAsString(); +} + +void TextNodeDumper::VisitConstantArrayType(const ConstantArrayType *T) { + OS << " " << T->getSize(); + VisitArrayType(T); +} + +void TextNodeDumper::VisitVariableArrayType(const VariableArrayType *T) { + OS << " "; + dumpSourceRange(T->getBracketsRange()); + VisitArrayType(T); +} + +void TextNodeDumper::VisitDependentSizedArrayType( + const DependentSizedArrayType *T) { + VisitArrayType(T); + OS << " "; + dumpSourceRange(T->getBracketsRange()); +} + +void TextNodeDumper::VisitDependentSizedExtVectorType( + const DependentSizedExtVectorType *T) { + OS << " "; + dumpLocation(T->getAttributeLoc()); +} + +void TextNodeDumper::VisitVectorType(const VectorType *T) { + switch (T->getVectorKind()) { + case VectorType::GenericVector: + break; + case VectorType::AltiVecVector: + OS << " altivec"; + break; + case VectorType::AltiVecPixel: + OS << " altivec pixel"; + break; + case VectorType::AltiVecBool: + OS << " altivec bool"; + break; + case VectorType::NeonVector: + OS << " neon"; + break; + case VectorType::NeonPolyVector: + OS << " neon poly"; + break; + } + OS << " " << T->getNumElements(); +} + +void TextNodeDumper::VisitFunctionType(const FunctionType *T) { + auto EI = T->getExtInfo(); + if (EI.getNoReturn()) + OS << " noreturn"; + if (EI.getProducesResult()) + OS << " produces_result"; + if (EI.getHasRegParm()) + OS << " regparm " << EI.getRegParm(); + OS << " " << FunctionType::getNameForCallConv(EI.getCC()); +} + +void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) { + auto EPI = T->getExtProtoInfo(); + if (EPI.HasTrailingReturn) + OS << " trailing_return"; + if (T->isConst()) + OS << " const"; + if (T->isVolatile()) + OS << " volatile"; + if (T->isRestrict()) + OS << " restrict"; + switch (EPI.RefQualifier) { + case RQ_None: + break; + case RQ_LValue: + OS << " &"; + break; + case RQ_RValue: + OS << " &&"; + break; + } + // FIXME: Exception specification. + // FIXME: Consumed parameters. + VisitFunctionType(T); +} + +void TextNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *T) { + dumpDeclRef(T->getDecl()); +} + +void TextNodeDumper::VisitTypedefType(const TypedefType *T) { + dumpDeclRef(T->getDecl()); +} + +void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) { + switch (T->getUTTKind()) { + case UnaryTransformType::EnumUnderlyingType: + OS << " underlying_type"; + break; + } +} + +void TextNodeDumper::VisitTagType(const TagType *T) { + dumpDeclRef(T->getDecl()); +} + +void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { + OS << " depth " << T->getDepth() << " index " << T->getIndex(); + if (T->isParameterPack()) + OS << " pack"; + dumpDeclRef(T->getDecl()); +} + +void TextNodeDumper::VisitAutoType(const AutoType *T) { + if (T->isDecltypeAuto()) + OS << " decltype(auto)"; + if (!T->isDeduced()) + OS << " undeduced"; +} + +void TextNodeDumper::VisitTemplateSpecializationType( + const TemplateSpecializationType *T) { + if (T->isTypeAlias()) + OS << " alias"; + OS << " "; + T->getTemplateName().dump(OS); +} + +void TextNodeDumper::VisitInjectedClassNameType( + const InjectedClassNameType *T) { + dumpDeclRef(T->getDecl()); +} + +void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) { + dumpDeclRef(T->getDecl()); +} + +void TextNodeDumper::VisitPackExpansionType(const PackExpansionType *T) { + if (auto N = T->getNumExpansions()) + OS << " expansions " << *N; +} diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index f79a59712a41..0dbc88c04521 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) @@ -592,28 +600,6 @@ bool Type::isObjCClassOrClassKindOfType() const { return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType(); } -/// Was this type written with the special inert-in-MRC __unsafe_unretained -/// qualifier? -/// -/// This approximates the answer to the following question: if this -/// translation unit were compiled in ARC, would this type be qualified -/// with __unsafe_unretained? -bool Type::isObjCInertUnsafeUnretainedType() const { - const Type *cur = this; - while (true) { - if (const auto attributed = dyn_cast<AttributedType>(cur)) { - if (attributed->getAttrKind() == - AttributedType::attr_objc_inert_unsafe_unretained) - return true; - } - - // Single-step desugar until we run out of sugar. - QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType(); - if (next.getTypePtr() == cur) return false; - cur = next.getTypePtr(); - } -} - ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can, ArrayRef<ObjCProtocolDecl *> protocols) @@ -1641,6 +1627,16 @@ TagDecl *Type::getAsTagDecl() const { return nullptr; } +bool Type::hasAttr(attr::Kind AK) const { + const Type *Cur = this; + while (const auto *AT = Cur->getAs<AttributedType>()) { + if (AT->getAttrKind() == AK) + return true; + Cur = AT->getEquivalentType().getTypePtr(); + } + return false; +} + namespace { class GetContainedDeducedTypeVisitor : @@ -1977,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; @@ -2604,7 +2601,8 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType( : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true, /*VariablyModified=*/false, NNS && NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name), NumArgs(Args.size()) { + NNS(NNS), Name(Name) { + DependentTemplateSpecializationTypeBits.NumArgs = Args.size(); assert((!NNS || NNS->isDependent()) && "DependentTemplateSpecializatonType requires dependent qualifier"); TemplateArgument *ArgBuffer = getArgBuffer(); @@ -2796,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."); @@ -2830,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"; @@ -2844,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()) @@ -2873,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 @@ -2889,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()) @@ -2904,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 @@ -2915,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; } @@ -2932,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 { @@ -2981,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; @@ -3029,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()); @@ -3056,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 { @@ -3154,118 +3172,81 @@ 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; } bool AttributedType::isQualifier() const { + // FIXME: Generate this with TableGen. switch (getAttrKind()) { // These are type qualifiers in the traditional C sense: they annotate // something about a specific value/variable of a type. (They aren't // always part of the canonical type, though.) - case AttributedType::attr_address_space: - case AttributedType::attr_objc_gc: - case AttributedType::attr_objc_ownership: - case AttributedType::attr_objc_inert_unsafe_unretained: - case AttributedType::attr_nonnull: - case AttributedType::attr_nullable: - case AttributedType::attr_null_unspecified: - case AttributedType::attr_lifetimebound: + case attr::ObjCGC: + case attr::ObjCOwnership: + case attr::ObjCInertUnsafeUnretained: + case attr::TypeNonNull: + case attr::TypeNullable: + case attr::TypeNullUnspecified: + case attr::LifetimeBound: return true; - // These aren't qualifiers; they rewrite the modified type to be a - // semantically different type. - case AttributedType::attr_regparm: - case AttributedType::attr_vector_size: - case AttributedType::attr_neon_vector_type: - case AttributedType::attr_neon_polyvector_type: - case AttributedType::attr_pcs: - case AttributedType::attr_pcs_vfp: - case AttributedType::attr_noreturn: - case AttributedType::attr_cdecl: - case AttributedType::attr_fastcall: - case AttributedType::attr_stdcall: - case AttributedType::attr_thiscall: - case AttributedType::attr_regcall: - case AttributedType::attr_pascal: - case AttributedType::attr_swiftcall: - case AttributedType::attr_vectorcall: - case AttributedType::attr_inteloclbicc: - case AttributedType::attr_preserve_most: - case AttributedType::attr_preserve_all: - case AttributedType::attr_ms_abi: - case AttributedType::attr_sysv_abi: - case AttributedType::attr_ptr32: - case AttributedType::attr_ptr64: - case AttributedType::attr_sptr: - case AttributedType::attr_uptr: - case AttributedType::attr_objc_kindof: - case AttributedType::attr_ns_returns_retained: - case AttributedType::attr_nocf_check: + // All other type attributes aren't qualifiers; they rewrite the modified + // type to be a semantically different type. + default: return false; } - llvm_unreachable("bad attributed type kind"); } bool AttributedType::isMSTypeSpec() const { + // FIXME: Generate this with TableGen? switch (getAttrKind()) { - default: return false; - case attr_ptr32: - case attr_ptr64: - case attr_sptr: - case attr_uptr: + default: return false; + case attr::Ptr32: + case attr::Ptr64: + case attr::SPtr: + case attr::UPtr: return true; } llvm_unreachable("invalid attr kind"); } bool AttributedType::isCallingConv() const { + // FIXME: Generate this with TableGen. switch (getAttrKind()) { - case attr_ptr32: - case attr_ptr64: - case attr_sptr: - case attr_uptr: - case attr_address_space: - case attr_regparm: - case attr_vector_size: - case attr_neon_vector_type: - case attr_neon_polyvector_type: - case attr_objc_gc: - case attr_objc_ownership: - case attr_objc_inert_unsafe_unretained: - case attr_noreturn: - case attr_nonnull: - case attr_ns_returns_retained: - case attr_nullable: - case attr_null_unspecified: - case attr_objc_kindof: - case attr_nocf_check: - case attr_lifetimebound: - return false; - - case attr_pcs: - case attr_pcs_vfp: - case attr_cdecl: - case attr_fastcall: - case attr_stdcall: - case attr_thiscall: - case attr_regcall: - case attr_swiftcall: - case attr_vectorcall: - case attr_pascal: - case attr_ms_abi: - case attr_sysv_abi: - case attr_inteloclbicc: - case attr_preserve_most: - case attr_preserve_all: + default: return false; + case attr::Pcs: + case attr::CDecl: + case attr::FastCall: + case attr::StdCall: + case attr::ThisCall: + case attr::RegCall: + case attr::SwiftCall: + case attr::VectorCall: + case attr::AArch64VectorPcs: + case attr::Pascal: + case attr::MSABI: + case attr::SysVABI: + case attr::IntelOclBicc: + case attr::PreserveMost: + case attr::PreserveAll: return true; } llvm_unreachable("invalid attr kind"); @@ -3284,11 +3265,12 @@ SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, QualType Canon, const TemplateArgument &ArgPack) : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true), - Replaced(Param), - Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) {} + Replaced(Param), Arguments(ArgPack.pack_begin()) { + SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size(); +} TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const { - return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); + return TemplateArgument(llvm::makeArrayRef(Arguments, getNumArgs())); } void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) { @@ -3335,8 +3317,10 @@ TemplateSpecializationType(TemplateName T, Canon.isNull()? true : Canon->isDependentType(), Canon.isNull()? true : Canon->isInstantiationDependentType(), false, - T.containsUnexpandedParameterPack()), - Template(T), NumArgs(Args.size()), TypeAlias(!AliasedType.isNull()) { + T.containsUnexpandedParameterPack()), Template(T) { + TemplateSpecializationTypeBits.NumArgs = Args.size(); + TemplateSpecializationTypeBits.TypeAlias = !AliasedType.isNull(); + assert(!T.getAsDependentTemplateName() && "Use DependentTemplateSpecializationType for dependent template-name"); assert((T.getKind() == TemplateName::Template || @@ -3365,7 +3349,7 @@ TemplateSpecializationType(TemplateName T, } // Store the aliased type if this is a type alias template specialization. - if (TypeAlias) { + if (isTypeAlias()) { auto *Begin = reinterpret_cast<TemplateArgument *>(this + 1); *reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType; } @@ -3708,23 +3692,18 @@ LinkageInfo Type::getLinkageAndVisibility() const { return LinkageComputer{}.getTypeLinkageAndVisibility(this); } -Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const { - QualType type(this, 0); - do { +Optional<NullabilityKind> +Type::getNullability(const ASTContext &Context) const { + QualType Type(this, 0); + while (const auto *AT = Type->getAs<AttributedType>()) { // Check whether this is an attributed type with nullability // information. - if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) { - if (auto nullability = attributed->getImmediateNullability()) - return nullability; - } - - // Desugar the type. If desugaring does nothing, we're done. - QualType desugared = type.getSingleStepDesugaredType(context); - if (desugared.getTypePtr() == type.getTypePtr()) - return None; + if (auto Nullability = AT->getImmediateNullability()) + return Nullability; - type = desugared; - } while (true); + Type = AT->getEquivalentType(); + } + return None; } bool Type::canHaveNullability(bool ResultIfUnknown) const { @@ -3796,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: @@ -3837,12 +3819,13 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { llvm_unreachable("bad type kind!"); } -llvm::Optional<NullabilityKind> AttributedType::getImmediateNullability() const { - if (getAttrKind() == AttributedType::attr_nonnull) +llvm::Optional<NullabilityKind> +AttributedType::getImmediateNullability() const { + if (getAttrKind() == attr::TypeNonNull) return NullabilityKind::NonNull; - if (getAttrKind() == AttributedType::attr_nullable) + if (getAttrKind() == attr::TypeNullable) return NullabilityKind::Nullable; - if (getAttrKind() == AttributedType::attr_null_unspecified) + if (getAttrKind() == attr::TypeNullUnspecified) return NullabilityKind::Unspecified; return None; } @@ -4032,17 +4015,26 @@ CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { } void clang::FixedPointValueToString(SmallVectorImpl<char> &Str, - const llvm::APSInt &Val, unsigned Scale, - unsigned Radix) { - llvm::APSInt ScaleVal = llvm::APSInt::getUnsigned(1ULL << Scale); - llvm::APSInt IntPart = Val / ScaleVal; - llvm::APSInt FractPart = Val % ScaleVal; - llvm::APSInt RadixInt = llvm::APSInt::getUnsigned(Radix); + llvm::APSInt Val, unsigned Scale) { + if (Val.isSigned() && Val.isNegative() && Val != -Val) { + Val = -Val; + Str.push_back('-'); + } + + llvm::APSInt IntPart = Val >> Scale; + + // Add 4 digits to hold the value after multiplying 10 (the radix) + unsigned Width = Val.getBitWidth() + 4; + llvm::APInt FractPart = Val.zextOrTrunc(Scale).zext(Width); + llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width); + llvm::APInt RadixInt = llvm::APInt(Width, 10); - IntPart.toString(Str, Radix); + IntPart.toString(Str, /*radix=*/10); Str.push_back('.'); do { - (FractPart * RadixInt / ScaleVal).toString(Str, Radix); - FractPart = (FractPart * RadixInt) % ScaleVal; - } while (FractPart.getExtValue()); + (FractPart * RadixInt) + .lshr(Scale) + .toString(Str, /*radix=*/10, Val.isSigned()); + FractPart = (FractPart * RadixInt) & FractPartMask; + } while (FractPart != 0); } diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index e4fd6f106e33..b7b2f188d716 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: @@ -404,11 +407,11 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { } SourceLocation TypeLoc::findNullabilityLoc() const { - if (auto attributedLoc = getAs<AttributedTypeLoc>()) { - if (attributedLoc.getAttrKind() == AttributedType::attr_nullable || - attributedLoc.getAttrKind() == AttributedType::attr_nonnull || - attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified) - return attributedLoc.getAttrNameLoc(); + if (auto ATL = getAs<AttributedTypeLoc>()) { + const Attr *A = ATL.getAttr(); + if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) || + isa<TypeNullUnspecifiedAttr>(A))) + return A->getLocation(); } return {}; diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index e032c312aa12..32c75afb4381 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -117,9 +117,7 @@ namespace { void spaceBeforePlaceHolder(raw_ostream &OS); void printTypeSpec(NamedDecl *D, raw_ostream &OS); - void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS); void printBefore(QualType T, raw_ostream &OS); - void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS); void printAfter(QualType T, raw_ostream &OS); void AppendScope(DeclContext *DC, raw_ostream &OS); void printTag(TagDecl *T, raw_ostream &OS); @@ -129,6 +127,10 @@ namespace { void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \ void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS); #include "clang/AST/TypeNodes.def" + + private: + void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS); + void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS); }; } // namespace @@ -160,8 +162,15 @@ void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) { OS << ' '; } +static SplitQualType splitAccordingToPolicy(QualType QT, + const PrintingPolicy &Policy) { + if (Policy.PrintCanonicalTypes) + QT = QT.getCanonicalType(); + return QT.split(); +} + void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) { - SplitQualType split = t.split(); + SplitQualType split = splitAccordingToPolicy(t, Policy); print(split.Ty, split.Quals, OS, PlaceHolder); } @@ -260,7 +269,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, } void TypePrinter::printBefore(QualType T, raw_ostream &OS) { - SplitQualType Split = T.split(); + SplitQualType Split = splitAccordingToPolicy(T, Policy); // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2 // at this level. @@ -320,7 +329,7 @@ void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) { } void TypePrinter::printAfter(QualType t, raw_ostream &OS) { - SplitQualType split = t.split(); + SplitQualType split = splitAccordingToPolicy(t, Policy); printAfter(split.Ty, split.Quals, OS); } @@ -801,10 +810,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 +868,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 +1164,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(); } } @@ -1354,12 +1368,14 @@ void TypePrinter::printPackExpansionAfter(const PackExpansionType *T, void TypePrinter::printAttributedBefore(const AttributedType *T, raw_ostream &OS) { + // FIXME: Generate this with TableGen. + // Prefer the macro forms of the GC and ownership qualifiers. - if (T->getAttrKind() == AttributedType::attr_objc_gc || - T->getAttrKind() == AttributedType::attr_objc_ownership) + if (T->getAttrKind() == attr::ObjCGC || + T->getAttrKind() == attr::ObjCOwnership) return printBefore(T->getEquivalentType(), OS); - if (T->getAttrKind() == AttributedType::attr_objc_kindof) + if (T->getAttrKind() == attr::ObjCKindOf) OS << "__kindof "; printBefore(T->getModifiedType(), OS); @@ -1367,23 +1383,21 @@ void TypePrinter::printAttributedBefore(const AttributedType *T, if (T->isMSTypeSpec()) { switch (T->getAttrKind()) { default: return; - case AttributedType::attr_ptr32: OS << " __ptr32"; break; - case AttributedType::attr_ptr64: OS << " __ptr64"; break; - case AttributedType::attr_sptr: OS << " __sptr"; break; - case AttributedType::attr_uptr: OS << " __uptr"; break; + case attr::Ptr32: OS << " __ptr32"; break; + case attr::Ptr64: OS << " __ptr64"; break; + case attr::SPtr: OS << " __sptr"; break; + case attr::UPtr: OS << " __uptr"; break; } spaceBeforePlaceHolder(OS); } // Print nullability type specifiers. - if (T->getAttrKind() == AttributedType::attr_nonnull || - T->getAttrKind() == AttributedType::attr_nullable || - T->getAttrKind() == AttributedType::attr_null_unspecified) { - if (T->getAttrKind() == AttributedType::attr_nonnull) + if (T->getImmediateNullability()) { + if (T->getAttrKind() == attr::TypeNonNull) OS << " _Nonnull"; - else if (T->getAttrKind() == AttributedType::attr_nullable) + else if (T->getAttrKind() == attr::TypeNullable) OS << " _Nullable"; - else if (T->getAttrKind() == AttributedType::attr_null_unspecified) + else if (T->getAttrKind() == attr::TypeNullUnspecified) OS << " _Null_unspecified"; else llvm_unreachable("unhandled nullability"); @@ -1393,140 +1407,96 @@ void TypePrinter::printAttributedBefore(const AttributedType *T, void TypePrinter::printAttributedAfter(const AttributedType *T, raw_ostream &OS) { + // FIXME: Generate this with TableGen. + // Prefer the macro forms of the GC and ownership qualifiers. - if (T->getAttrKind() == AttributedType::attr_objc_gc || - T->getAttrKind() == AttributedType::attr_objc_ownership) + if (T->getAttrKind() == attr::ObjCGC || + T->getAttrKind() == attr::ObjCOwnership) return printAfter(T->getEquivalentType(), OS); - if (T->getAttrKind() == AttributedType::attr_objc_kindof) - return; - - // TODO: not all attributes are GCC-style attributes. - if (T->isMSTypeSpec()) - return; - - // Nothing to print after. - if (T->getAttrKind() == AttributedType::attr_nonnull || - T->getAttrKind() == AttributedType::attr_nullable || - T->getAttrKind() == AttributedType::attr_null_unspecified) - return printAfter(T->getModifiedType(), OS); - // If this is a calling convention attribute, don't print the implicit CC from // the modified type. SaveAndRestore<bool> MaybeSuppressCC(InsideCCAttribute, T->isCallingConv()); printAfter(T->getModifiedType(), OS); + // Some attributes are printed as qualifiers before the type, so we have + // nothing left to do. + if (T->getAttrKind() == attr::ObjCKindOf || + T->isMSTypeSpec() || T->getImmediateNullability()) + return; + // Don't print the inert __unsafe_unretained attribute at all. - if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained) + if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained) return; // Don't print ns_returns_retained unless it had an effect. - if (T->getAttrKind() == AttributedType::attr_ns_returns_retained && + if (T->getAttrKind() == attr::NSReturnsRetained && !T->getEquivalentType()->castAs<FunctionType>() ->getExtInfo().getProducesResult()) return; - // Print nullability type specifiers that occur after - if (T->getAttrKind() == AttributedType::attr_nonnull || - T->getAttrKind() == AttributedType::attr_nullable || - T->getAttrKind() == AttributedType::attr_null_unspecified) { - if (T->getAttrKind() == AttributedType::attr_nonnull) - OS << " _Nonnull"; - else if (T->getAttrKind() == AttributedType::attr_nullable) - OS << " _Nullable"; - else if (T->getAttrKind() == AttributedType::attr_null_unspecified) - OS << " _Null_unspecified"; - else - llvm_unreachable("unhandled nullability"); - + if (T->getAttrKind() == attr::LifetimeBound) { + OS << " [[clang::lifetimebound]]"; return; } - if (T->getAttrKind() == AttributedType::attr_lifetimebound) { - OS << " [[clang::lifetimebound]]"; + // The printing of the address_space attribute is handled by the qualifier + // since it is still stored in the qualifier. Return early to prevent printing + // this twice. + if (T->getAttrKind() == attr::AddressSpace) return; - } OS << " __attribute__(("; switch (T->getAttrKind()) { - case AttributedType::attr_lifetimebound: - case AttributedType::attr_nonnull: - case AttributedType::attr_nullable: - case AttributedType::attr_null_unspecified: - case AttributedType::attr_objc_gc: - case AttributedType::attr_objc_inert_unsafe_unretained: - case AttributedType::attr_objc_kindof: - case AttributedType::attr_objc_ownership: - case AttributedType::attr_ptr32: - case AttributedType::attr_ptr64: - case AttributedType::attr_sptr: - case AttributedType::attr_uptr: - llvm_unreachable("This attribute should have been handled already"); +#define TYPE_ATTR(NAME) +#define DECL_OR_TYPE_ATTR(NAME) +#define ATTR(NAME) case attr::NAME: +#include "clang/Basic/AttrList.inc" + llvm_unreachable("non-type attribute attached to type"); - case AttributedType::attr_address_space: - OS << "address_space("; - // FIXME: printing the raw LangAS value is wrong. This should probably - // use the same code as Qualifiers::print() - OS << (unsigned)T->getEquivalentType().getAddressSpace(); - OS << ')'; + case attr::OpenCLPrivateAddressSpace: + case attr::OpenCLGlobalAddressSpace: + case attr::OpenCLLocalAddressSpace: + case attr::OpenCLConstantAddressSpace: + case attr::OpenCLGenericAddressSpace: + // FIXME: Update printAttributedBefore to print these once we generate + // AttributedType nodes for them. break; - case AttributedType::attr_vector_size: - OS << "__vector_size__("; - if (const auto *vector = T->getEquivalentType()->getAs<VectorType>()) { - OS << vector->getNumElements(); - OS << " * sizeof("; - print(vector->getElementType(), OS, StringRef()); - OS << ')'; - } - OS << ')'; - break; - - case AttributedType::attr_neon_vector_type: - case AttributedType::attr_neon_polyvector_type: { - if (T->getAttrKind() == AttributedType::attr_neon_vector_type) - OS << "neon_vector_type("; - else - OS << "neon_polyvector_type("; - const auto *vector = T->getEquivalentType()->getAs<VectorType>(); - OS << vector->getNumElements(); - OS << ')'; - break; - } - - case AttributedType::attr_regparm: { - // FIXME: When Sema learns to form this AttributedType, avoid printing the - // attribute again in printFunctionProtoAfter. - OS << "regparm("; - QualType t = T->getEquivalentType(); - while (!t->isFunctionType()) - t = t->getPointeeType(); - OS << t->getAs<FunctionType>()->getRegParmType(); - OS << ')'; - break; - } + case attr::LifetimeBound: + case attr::TypeNonNull: + case attr::TypeNullable: + case attr::TypeNullUnspecified: + case attr::ObjCGC: + case attr::ObjCInertUnsafeUnretained: + case attr::ObjCKindOf: + case attr::ObjCOwnership: + case attr::Ptr32: + case attr::Ptr64: + case attr::SPtr: + case attr::UPtr: + case attr::AddressSpace: + llvm_unreachable("This attribute should have been handled already"); - case AttributedType::attr_ns_returns_retained: + case attr::NSReturnsRetained: OS << "ns_returns_retained"; break; // FIXME: When Sema learns to form this AttributedType, avoid printing the // attribute again in printFunctionProtoAfter. - case AttributedType::attr_noreturn: OS << "noreturn"; break; - case AttributedType::attr_nocf_check: OS << "nocf_check"; break; - case AttributedType::attr_cdecl: OS << "cdecl"; break; - case AttributedType::attr_fastcall: OS << "fastcall"; break; - case AttributedType::attr_stdcall: OS << "stdcall"; break; - case AttributedType::attr_thiscall: OS << "thiscall"; break; - case AttributedType::attr_swiftcall: OS << "swiftcall"; break; - case AttributedType::attr_vectorcall: OS << "vectorcall"; break; - case AttributedType::attr_pascal: OS << "pascal"; break; - case AttributedType::attr_ms_abi: OS << "ms_abi"; break; - case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break; - case AttributedType::attr_regcall: OS << "regcall"; break; - case AttributedType::attr_pcs: - case AttributedType::attr_pcs_vfp: { + case attr::AnyX86NoCfCheck: OS << "nocf_check"; break; + case attr::CDecl: OS << "cdecl"; break; + case attr::FastCall: OS << "fastcall"; break; + case attr::StdCall: OS << "stdcall"; break; + case attr::ThisCall: OS << "thiscall"; break; + case attr::SwiftCall: OS << "swiftcall"; break; + case attr::VectorCall: OS << "vectorcall"; break; + case attr::Pascal: OS << "pascal"; break; + case attr::MSABI: OS << "ms_abi"; break; + case attr::SysVABI: OS << "sysv_abi"; break; + case attr::RegCall: OS << "regcall"; break; + case attr::Pcs: { OS << "pcs("; QualType t = T->getEquivalentType(); while (!t->isFunctionType()) @@ -1536,15 +1506,18 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, OS << ')'; break; } - - case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break; - case AttributedType::attr_preserve_most: + case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break; + case attr::IntelOclBicc: OS << "inteloclbicc"; break; + case attr::PreserveMost: OS << "preserve_most"; break; - case AttributedType::attr_preserve_all: + case attr::PreserveAll: OS << "preserve_all"; break; + case attr::NoDeref: + OS << "noderef"; + break; } OS << "))"; } @@ -1851,6 +1824,12 @@ std::string QualType::getAsString(const Type *ty, Qualifiers qs, return buffer; } +void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy, + const Twine &PlaceHolder, unsigned Indentation) const { + print(splitAccordingToPolicy(*this, Policy), OS, Policy, PlaceHolder, + Indentation); +} + void QualType::print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, unsigned Indentation) { @@ -1860,6 +1839,12 @@ void QualType::print(const Type *ty, Qualifiers qs, TypePrinter(policy, Indentation).print(ty, qs, OS, PH); } +void QualType::getAsStringInternal(std::string &Str, + const PrintingPolicy &Policy) const { + return getAsStringInternal(splitAccordingToPolicy(*this, Policy), Str, + Policy); +} + void QualType::getAsStringInternal(const Type *ty, Qualifiers qs, std::string &buffer, const PrintingPolicy &policy) { diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index dfc5774ab498..846a6085743e 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -2105,8 +2105,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { const CXXMethodDecl *MD = I.second; ThunkInfoVectorTy ThunksVector = Thunks[MD]; - llvm::sort(ThunksVector.begin(), ThunksVector.end(), - [](const ThunkInfo &LHS, const ThunkInfo &RHS) { + llvm::sort(ThunksVector, [](const ThunkInfo &LHS, const ThunkInfo &RHS) { assert(LHS.Method == nullptr && RHS.Method == nullptr); return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return); }); @@ -2206,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() { } @@ -3345,8 +3343,7 @@ static bool rebucketPaths(VPtrInfoVector &Paths) { PathsSorted.reserve(Paths.size()); for (auto& P : Paths) PathsSorted.push_back(*P); - llvm::sort(PathsSorted.begin(), PathsSorted.end(), - [](const VPtrInfo &LHS, const VPtrInfo &RHS) { + llvm::sort(PathsSorted, [](const VPtrInfo &LHS, const VPtrInfo &RHS) { return LHS.MangledPath < RHS.MangledPath; }); bool Changed = false; @@ -3409,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; } } @@ -3488,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); } |
