#include "clang/AST/ASTImporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclVisitor.h"
public DeclVisitor<ASTNodeImporter, Decl *>,
public StmtVisitor<ASTNodeImporter, Stmt *> {
ASTImporter &Importer;
-
+
public:
explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) { }
// 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 VisitDecltypeType(const DecltypeType *T);
QualType VisitUnaryTransformType(const UnaryTransformType *T);
QualType VisitAutoType(const AutoType *T);
+ QualType VisitInjectedClassNameType(const InjectedClassNameType *T);
// FIXME: DependentDecltypeType
QualType VisitRecordType(const RecordType *T);
QualType VisitEnumType(const EnumType *T);
- // FIXME: TemplateTypeParmType
- // FIXME: SubstTemplateTypeParmType
+ 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);
// FIXME: DependentNameType
// Importing declarations
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
- SourceLocation &Loc);
+ NamedDecl *&ToD, SourceLocation &Loc);
void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
+
+ bool ImportCastPath(CastExpr *E, CXXCastPath &Path);
+
+ typedef DesignatedInitExpr::Designator Designator;
+ Designator ImportDesignator(const Designator &D);
+
/// \brief What we should import from the definition.
enum ImportDefinitionKind {
TemplateParameterList *ImportTemplateParameterList(
TemplateParameterList *Params);
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
+ TemplateArgumentLoc ImportTemplateArgumentLoc(
+ const TemplateArgumentLoc &TALoc, bool &Error);
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
Decl *VisitDecl(Decl *D);
+ Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
+ Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
Decl *VisitTypedefDecl(TypedefDecl *D);
Decl *VisitTypeAliasDecl(TypeAliasDecl *D);
+ Decl *VisitLabelDecl(LabelDecl *D);
Decl *VisitEnumDecl(EnumDecl *D);
Decl *VisitRecordDecl(RecordDecl *D);
Decl *VisitEnumConstantDecl(EnumConstantDecl *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);
+
+ ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list);
Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *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);
+ // FIXME: MSAsmStmt
+ // FIXME: SEHExceptStmt
+ // FIXME: SEHFinallyStmt
+ // FIXME: SEHTryStmt
+ // FIXME: SEHLeaveStmt
+ // FIXME: CapturedStmt
+ Stmt *VisitCXXCatchStmt(CXXCatchStmt *S);
+ Stmt *VisitCXXTryStmt(CXXTryStmt *S);
+ Stmt *VisitCXXForRangeStmt(CXXForRangeStmt *S);
+ // FIXME: MSDependentExistsStmt
+ Stmt *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
+ Stmt *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
+ Stmt *VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S);
+ Stmt *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
+ Stmt *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
+ Stmt *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
+ Stmt *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
// Importing expressions
Expr *VisitExpr(Expr *E);
+ 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 *VisitCStyleCastExpr(CStyleCastExpr *E);
- };
-}
-using namespace clang;
+ 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 *VisitCXXNewExpr(CXXNewExpr *CE);
+ Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
+ Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
+ Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
+ Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
+ Expr *VisitCXXThisExpr(CXXThisExpr *E);
+ Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
+ Expr *VisitMemberExpr(MemberExpr *E);
+ Expr *VisitCallExpr(CallExpr *E);
+ Expr *VisitInitListExpr(InitListExpr *E);
+ Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
+ Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
+ Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
+ Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+ Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
+
+
+ template<typename IIter, typename OIter>
+ void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) {
+ typedef typename std::remove_reference<decltype(*Obegin)>::type ItemT;
+ ASTImporter &ImporterRef = Importer;
+ std::transform(Ibegin, Iend, Obegin,
+ [&ImporterRef](ItemT From) -> ItemT {
+ return ImporterRef.Import(From);
+ });
+ }
-//----------------------------------------------------------------------------
-// Structural Equivalence
-//----------------------------------------------------------------------------
+ template<typename IIter, typename OIter>
+ bool ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
+ typedef typename std::remove_reference<decltype(**Obegin)>::type ItemT;
+ ASTImporter &ImporterRef = Importer;
+ bool Failed = false;
+ std::transform(Ibegin, Iend, Obegin,
+ [&ImporterRef, &Failed](ItemT *From) -> ItemT * {
+ ItemT *To = cast_or_null<ItemT>(
+ ImporterRef.Import(From));
+ if (!To && From)
+ Failed = true;
+ return To;
+ });
+ return Failed;
+ }
-namespace {
- struct StructuralEquivalenceContext {
- /// \brief AST contexts for which we are checking structural equivalence.
- ASTContext &C1, &C2;
-
- /// \brief The set of "tentative" equivalences between two canonical
- /// declarations, mapping from a declaration in the first context to the
- /// declaration in the second context that we believe to be equivalent.
- llvm::DenseMap<Decl *, Decl *> TentativeEquivalences;
-
- /// \brief Queue of declarations in the first context whose equivalence
- /// with a declaration in the second context still needs to be verified.
- std::deque<Decl *> DeclsToCheck;
-
- /// \brief Declaration (from, to) pairs that are known not to be equivalent
- /// (which we have already complained about).
- llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls;
-
- /// \brief Whether we're being strict about the spelling of types when
- /// unifying two types.
- bool StrictTypeSpelling;
-
- /// \brief Whether to complain about failures.
- bool Complain;
-
- /// \brief \c true if the last diagnostic came from C2.
- bool LastDiagFromC2;
-
- StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2,
- llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls,
- bool StrictTypeSpelling = false,
- bool Complain = true)
- : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls),
- StrictTypeSpelling(StrictTypeSpelling), Complain(Complain),
- LastDiagFromC2(false) {}
-
- /// \brief Determine whether the two declarations are structurally
- /// equivalent.
- bool IsStructurallyEquivalent(Decl *D1, Decl *D2);
-
- /// \brief Determine whether the two types are structurally equivalent.
- bool IsStructurallyEquivalent(QualType T1, QualType T2);
-
- private:
- /// \brief Finish checking all of the structural equivalences.
- ///
- /// \returns true if an error occurred, false otherwise.
- bool Finish();
-
- public:
- DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) {
- assert(Complain && "Not allowed to complain");
- if (LastDiagFromC2)
- C1.getDiagnostics().notePriorDiagnosticFrom(C2.getDiagnostics());
- LastDiagFromC2 = false;
- return C1.getDiagnostics().Report(Loc, DiagID);
+ template<typename InContainerTy, typename OutContainerTy>
+ bool ImportContainerChecked(const InContainerTy &InContainer,
+ OutContainerTy &OutContainer) {
+ return ImportArrayChecked(InContainer.begin(), InContainer.end(),
+ OutContainer.begin());
}
- DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) {
- assert(Complain && "Not allowed to complain");
- if (!LastDiagFromC2)
- C2.getDiagnostics().notePriorDiagnosticFrom(C1.getDiagnostics());
- LastDiagFromC2 = true;
- return C2.getDiagnostics().Report(Loc, DiagID);
+ template<typename InContainerTy, typename OIter>
+ bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
+ return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin);
}
+
+ // Importing overrides.
+ void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod);
};
}
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- QualType T1, QualType T2);
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- Decl *D1, Decl *D2);
+//----------------------------------------------------------------------------
+// Import Types
+//----------------------------------------------------------------------------
-/// \brief Determine structural equivalence of two expressions.
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- Expr *E1, Expr *E2) {
- if (!E1 || !E2)
- return E1 == E2;
-
- // FIXME: Actually perform a structural comparison!
- return true;
-}
+using namespace clang;
-/// \brief Determine whether two identifiers are equivalent.
-static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
- const IdentifierInfo *Name2) {
- if (!Name1 || !Name2)
- return Name1 == Name2;
-
- return Name1->getName() == Name2->getName();
+QualType ASTNodeImporter::VisitType(const Type *T) {
+ Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
+ << T->getTypeClassName();
+ return QualType();
}
-/// \brief Determine whether two nested-name-specifiers are equivalent.
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- NestedNameSpecifier *NNS1,
- NestedNameSpecifier *NNS2) {
- // FIXME: Implement!
- return true;
+QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
+ QualType UnderlyingType = Importer.Import(T->getValueType());
+ if(UnderlyingType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getAtomicType(UnderlyingType);
}
-/// \brief Determine whether two template arguments are equivalent.
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- const TemplateArgument &Arg1,
- const TemplateArgument &Arg2) {
- if (Arg1.getKind() != Arg2.getKind())
- return false;
+QualType 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 SHARED_SINGLETON_TYPE(Expansion)
+#define BUILTIN_TYPE(Id, SingletonId) \
+ case BuiltinType::Id: return Importer.getToContext().SingletonId;
+#include "clang/AST/BuiltinTypes.def"
- switch (Arg1.getKind()) {
- case TemplateArgument::Null:
- return true;
-
- case TemplateArgument::Type:
- return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType());
+ // FIXME: for Char16, Char32, and NullPtr, make sure that the "to"
+ // context supports C++.
+
+ // FIXME: for ObjCId, ObjCClass, and ObjCSel, make sure that the "to"
+ // context supports ObjC.
- case TemplateArgument::Integral:
- if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(),
- Arg2.getIntegralType()))
- return false;
+ case BuiltinType::Char_U:
+ // The context we're importing from has an unsigned 'char'. If we're
+ // importing into a context with a signed 'char', translate to
+ // 'unsigned char' instead.
+ if (Importer.getToContext().getLangOpts().CharIsSigned)
+ return Importer.getToContext().UnsignedCharTy;
- return llvm::APSInt::isSameValue(Arg1.getAsIntegral(), Arg2.getAsIntegral());
-
- case TemplateArgument::Declaration:
- return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl());
+ return Importer.getToContext().CharTy;
+
+ case BuiltinType::Char_S:
+ // The context we're importing from has an unsigned 'char'. If we're
+ // importing into a context with a signed 'char', translate to
+ // 'unsigned char' instead.
+ if (!Importer.getToContext().getLangOpts().CharIsSigned)
+ return Importer.getToContext().SignedCharTy;
+
+ return Importer.getToContext().CharTy;
- case TemplateArgument::NullPtr:
- return true; // FIXME: Is this correct?
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ // FIXME: If not in C++, shall we translate to the C equivalent of
+ // wchar_t?
+ return Importer.getToContext().WCharTy;
+ }
- case TemplateArgument::Template:
- return IsStructurallyEquivalent(Context,
- Arg1.getAsTemplate(),
- Arg2.getAsTemplate());
+ llvm_unreachable("Invalid BuiltinType Kind!");
+}
- case TemplateArgument::TemplateExpansion:
- return IsStructurallyEquivalent(Context,
- Arg1.getAsTemplateOrTemplatePattern(),
- Arg2.getAsTemplateOrTemplatePattern());
+QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
+ QualType OrigT = Importer.Import(T->getOriginalType());
+ if (OrigT.isNull())
+ return QualType();
- case TemplateArgument::Expression:
- return IsStructurallyEquivalent(Context,
- Arg1.getAsExpr(), Arg2.getAsExpr());
-
- case TemplateArgument::Pack:
- if (Arg1.pack_size() != Arg2.pack_size())
- return false;
-
- for (unsigned I = 0, N = Arg1.pack_size(); I != N; ++I)
- if (!IsStructurallyEquivalent(Context,
- Arg1.pack_begin()[I],
- Arg2.pack_begin()[I]))
- return false;
-
- return true;
- }
-
- llvm_unreachable("Invalid template argument kind");
+ return Importer.getToContext().getDecayedType(OrigT);
}
-/// \brief Determine structural equivalence for the common part of array
-/// types.
-static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context,
- const ArrayType *Array1,
- const ArrayType *Array2) {
- if (!IsStructurallyEquivalent(Context,
- Array1->getElementType(),
- Array2->getElementType()))
- return false;
- if (Array1->getSizeModifier() != Array2->getSizeModifier())
- return false;
- if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers())
- return false;
+QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
- return true;
+ return Importer.getToContext().getComplexType(ToElementType);
}
-/// \brief Determine structural equivalence of two types.
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- QualType T1, QualType T2) {
- if (T1.isNull() || T2.isNull())
- return T1.isNull() && T2.isNull();
-
- if (!Context.StrictTypeSpelling) {
- // We aren't being strict about token-to-token equivalence of types,
- // so map down to the canonical type.
- T1 = Context.C1.getCanonicalType(T1);
- T2 = Context.C2.getCanonicalType(T2);
- }
-
- if (T1.getQualifiers() != T2.getQualifiers())
- return false;
-
- Type::TypeClass TC = T1->getTypeClass();
-
- if (T1->getTypeClass() != T2->getTypeClass()) {
- // Compare function types with prototypes vs. without prototypes as if
- // both did not have prototypes.
- if (T1->getTypeClass() == Type::FunctionProto &&
- T2->getTypeClass() == Type::FunctionNoProto)
- TC = Type::FunctionNoProto;
- else if (T1->getTypeClass() == Type::FunctionNoProto &&
- T2->getTypeClass() == Type::FunctionProto)
- TC = Type::FunctionNoProto;
- else
- return false;
- }
-
- switch (TC) {
- case Type::Builtin:
- // FIXME: Deal with Char_S/Char_U.
- if (cast<BuiltinType>(T1)->getKind() != cast<BuiltinType>(T2)->getKind())
- return false;
- break;
-
- case Type::Complex:
- if (!IsStructurallyEquivalent(Context,
- cast<ComplexType>(T1)->getElementType(),
- cast<ComplexType>(T2)->getElementType()))
- return false;
- break;
+QualType ASTNodeImporter::VisitPointerType(const PointerType *T) {
+ QualType ToPointeeType = Importer.Import(T->getPointeeType());
+ if (ToPointeeType.isNull())
+ return QualType();
- case Type::Adjusted:
- case Type::Decayed:
- if (!IsStructurallyEquivalent(Context,
- cast<AdjustedType>(T1)->getOriginalType(),
- cast<AdjustedType>(T2)->getOriginalType()))
- return false;
- break;
-
- case Type::Pointer:
- if (!IsStructurallyEquivalent(Context,
- cast<PointerType>(T1)->getPointeeType(),
- cast<PointerType>(T2)->getPointeeType()))
- return false;
- break;
-
- case Type::BlockPointer:
- if (!IsStructurallyEquivalent(Context,
- cast<BlockPointerType>(T1)->getPointeeType(),
- cast<BlockPointerType>(T2)->getPointeeType()))
- return false;
- break;
-
- case Type::LValueReference:
- case Type::RValueReference: {
- const ReferenceType *Ref1 = cast<ReferenceType>(T1);
- const ReferenceType *Ref2 = cast<ReferenceType>(T2);
- if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
- return false;
- if (Ref1->isInnerRef() != Ref2->isInnerRef())
- return false;
- if (!IsStructurallyEquivalent(Context,
- Ref1->getPointeeTypeAsWritten(),
- Ref2->getPointeeTypeAsWritten()))
- return false;
- break;
- }
-
- case Type::MemberPointer: {
- const MemberPointerType *MemPtr1 = cast<MemberPointerType>(T1);
- const MemberPointerType *MemPtr2 = cast<MemberPointerType>(T2);
- if (!IsStructurallyEquivalent(Context,
- MemPtr1->getPointeeType(),
- MemPtr2->getPointeeType()))
- return false;
- if (!IsStructurallyEquivalent(Context,
- QualType(MemPtr1->getClass(), 0),
- QualType(MemPtr2->getClass(), 0)))
- return false;
- break;
- }
-
- case Type::ConstantArray: {
- const ConstantArrayType *Array1 = cast<ConstantArrayType>(T1);
- const ConstantArrayType *Array2 = cast<ConstantArrayType>(T2);
- if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
- return false;
-
- if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
- return false;
- break;
- }
+ return Importer.getToContext().getPointerType(ToPointeeType);
+}
- case Type::IncompleteArray:
- if (!IsArrayStructurallyEquivalent(Context,
- cast<ArrayType>(T1),
- cast<ArrayType>(T2)))
- return false;
- break;
-
- case Type::VariableArray: {
- const VariableArrayType *Array1 = cast<VariableArrayType>(T1);
- const VariableArrayType *Array2 = cast<VariableArrayType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Array1->getSizeExpr(), Array2->getSizeExpr()))
- return false;
-
- if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
- return false;
-
- break;
- }
-
- case Type::DependentSizedArray: {
- const DependentSizedArrayType *Array1 = cast<DependentSizedArrayType>(T1);
- const DependentSizedArrayType *Array2 = cast<DependentSizedArrayType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Array1->getSizeExpr(), Array2->getSizeExpr()))
- return false;
-
- if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
- return false;
-
- break;
- }
-
- case Type::DependentSizedExtVector: {
- const DependentSizedExtVectorType *Vec1
- = cast<DependentSizedExtVectorType>(T1);
- const DependentSizedExtVectorType *Vec2
- = cast<DependentSizedExtVectorType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Vec1->getSizeExpr(), Vec2->getSizeExpr()))
- return false;
- if (!IsStructurallyEquivalent(Context,
- Vec1->getElementType(),
- Vec2->getElementType()))
- return false;
- break;
- }
-
- case Type::Vector:
- case Type::ExtVector: {
- const VectorType *Vec1 = cast<VectorType>(T1);
- const VectorType *Vec2 = cast<VectorType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Vec1->getElementType(),
- Vec2->getElementType()))
- return false;
- if (Vec1->getNumElements() != Vec2->getNumElements())
- return false;
- if (Vec1->getVectorKind() != Vec2->getVectorKind())
- return false;
- break;
- }
-
- case Type::FunctionProto: {
- const FunctionProtoType *Proto1 = cast<FunctionProtoType>(T1);
- const FunctionProtoType *Proto2 = cast<FunctionProtoType>(T2);
- if (Proto1->getNumParams() != Proto2->getNumParams())
- return false;
- for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I),
- Proto2->getParamType(I)))
- return false;
- }
- if (Proto1->isVariadic() != Proto2->isVariadic())
- return false;
- if (Proto1->getExceptionSpecType() != Proto2->getExceptionSpecType())
- return false;
- if (Proto1->getExceptionSpecType() == EST_Dynamic) {
- if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
- return false;
- for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context,
- Proto1->getExceptionType(I),
- Proto2->getExceptionType(I)))
- return false;
- }
- } else if (Proto1->getExceptionSpecType() == EST_ComputedNoexcept) {
- if (!IsStructurallyEquivalent(Context,
- Proto1->getNoexceptExpr(),
- Proto2->getNoexceptExpr()))
- return false;
- }
- if (Proto1->getTypeQuals() != Proto2->getTypeQuals())
- return false;
-
- // Fall through to check the bits common with FunctionNoProtoType.
- }
-
- case Type::FunctionNoProto: {
- const FunctionType *Function1 = cast<FunctionType>(T1);
- const FunctionType *Function2 = cast<FunctionType>(T2);
- if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
- Function2->getReturnType()))
- return false;
- if (Function1->getExtInfo() != Function2->getExtInfo())
- return false;
- break;
- }
-
- case Type::UnresolvedUsing:
- if (!IsStructurallyEquivalent(Context,
- cast<UnresolvedUsingType>(T1)->getDecl(),
- cast<UnresolvedUsingType>(T2)->getDecl()))
- return false;
-
- break;
-
- case Type::Attributed:
- if (!IsStructurallyEquivalent(Context,
- cast<AttributedType>(T1)->getModifiedType(),
- cast<AttributedType>(T2)->getModifiedType()))
- return false;
- if (!IsStructurallyEquivalent(Context,
- cast<AttributedType>(T1)->getEquivalentType(),
- cast<AttributedType>(T2)->getEquivalentType()))
- return false;
- break;
-
- case Type::Paren:
- if (!IsStructurallyEquivalent(Context,
- cast<ParenType>(T1)->getInnerType(),
- cast<ParenType>(T2)->getInnerType()))
- return false;
- break;
-
- case Type::Typedef:
- if (!IsStructurallyEquivalent(Context,
- cast<TypedefType>(T1)->getDecl(),
- cast<TypedefType>(T2)->getDecl()))
- return false;
- break;
-
- case Type::TypeOfExpr:
- if (!IsStructurallyEquivalent(Context,
- cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
- cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
- return false;
- break;
-
- case Type::TypeOf:
- if (!IsStructurallyEquivalent(Context,
- cast<TypeOfType>(T1)->getUnderlyingType(),
- cast<TypeOfType>(T2)->getUnderlyingType()))
- return false;
- break;
-
- case Type::UnaryTransform:
- if (!IsStructurallyEquivalent(Context,
- cast<UnaryTransformType>(T1)->getUnderlyingType(),
- cast<UnaryTransformType>(T1)->getUnderlyingType()))
- return false;
- break;
-
- case Type::Decltype:
- if (!IsStructurallyEquivalent(Context,
- cast<DecltypeType>(T1)->getUnderlyingExpr(),
- cast<DecltypeType>(T2)->getUnderlyingExpr()))
- return false;
- break;
-
- case Type::Auto:
- if (!IsStructurallyEquivalent(Context,
- cast<AutoType>(T1)->getDeducedType(),
- cast<AutoType>(T2)->getDeducedType()))
- return false;
- break;
-
- case Type::Record:
- case Type::Enum:
- if (!IsStructurallyEquivalent(Context,
- cast<TagType>(T1)->getDecl(),
- cast<TagType>(T2)->getDecl()))
- return false;
- break;
-
- case Type::TemplateTypeParm: {
- const TemplateTypeParmType *Parm1 = cast<TemplateTypeParmType>(T1);
- const TemplateTypeParmType *Parm2 = cast<TemplateTypeParmType>(T2);
- if (Parm1->getDepth() != Parm2->getDepth())
- return false;
- if (Parm1->getIndex() != Parm2->getIndex())
- return false;
- if (Parm1->isParameterPack() != Parm2->isParameterPack())
- return false;
-
- // Names of template type parameters are never significant.
- break;
- }
-
- case Type::SubstTemplateTypeParm: {
- const SubstTemplateTypeParmType *Subst1
- = cast<SubstTemplateTypeParmType>(T1);
- const SubstTemplateTypeParmType *Subst2
- = cast<SubstTemplateTypeParmType>(T2);
- if (!IsStructurallyEquivalent(Context,
- QualType(Subst1->getReplacedParameter(), 0),
- QualType(Subst2->getReplacedParameter(), 0)))
- return false;
- if (!IsStructurallyEquivalent(Context,
- Subst1->getReplacementType(),
- Subst2->getReplacementType()))
- return false;
- break;
- }
-
- case Type::SubstTemplateTypeParmPack: {
- const SubstTemplateTypeParmPackType *Subst1
- = cast<SubstTemplateTypeParmPackType>(T1);
- const SubstTemplateTypeParmPackType *Subst2
- = cast<SubstTemplateTypeParmPackType>(T2);
- if (!IsStructurallyEquivalent(Context,
- QualType(Subst1->getReplacedParameter(), 0),
- QualType(Subst2->getReplacedParameter(), 0)))
- return false;
- if (!IsStructurallyEquivalent(Context,
- Subst1->getArgumentPack(),
- Subst2->getArgumentPack()))
- return false;
- break;
- }
- case Type::TemplateSpecialization: {
- const TemplateSpecializationType *Spec1
- = cast<TemplateSpecializationType>(T1);
- const TemplateSpecializationType *Spec2
- = cast<TemplateSpecializationType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Spec1->getTemplateName(),
- Spec2->getTemplateName()))
- return false;
- if (Spec1->getNumArgs() != Spec2->getNumArgs())
- return false;
- for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context,
- Spec1->getArg(I), Spec2->getArg(I)))
- return false;
- }
- break;
- }
-
- case Type::Elaborated: {
- const ElaboratedType *Elab1 = cast<ElaboratedType>(T1);
- const ElaboratedType *Elab2 = cast<ElaboratedType>(T2);
- // CHECKME: what if a keyword is ETK_None or ETK_typename ?
- if (Elab1->getKeyword() != Elab2->getKeyword())
- return false;
- if (!IsStructurallyEquivalent(Context,
- Elab1->getQualifier(),
- Elab2->getQualifier()))
- return false;
- if (!IsStructurallyEquivalent(Context,
- Elab1->getNamedType(),
- Elab2->getNamedType()))
- return false;
- break;
- }
-
- case Type::InjectedClassName: {
- const InjectedClassNameType *Inj1 = cast<InjectedClassNameType>(T1);
- const InjectedClassNameType *Inj2 = cast<InjectedClassNameType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Inj1->getInjectedSpecializationType(),
- Inj2->getInjectedSpecializationType()))
- return false;
- break;
- }
-
- case Type::DependentName: {
- const DependentNameType *Typename1 = cast<DependentNameType>(T1);
- const DependentNameType *Typename2 = cast<DependentNameType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Typename1->getQualifier(),
- Typename2->getQualifier()))
- return false;
- if (!IsStructurallyEquivalent(Typename1->getIdentifier(),
- Typename2->getIdentifier()))
- return false;
-
- break;
- }
+QualType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) {
+ // FIXME: Check for blocks support in "to" context.
+ QualType ToPointeeType = Importer.Import(T->getPointeeType());
+ if (ToPointeeType.isNull())
+ return QualType();
- case Type::DependentTemplateSpecialization: {
- const DependentTemplateSpecializationType *Spec1 =
- cast<DependentTemplateSpecializationType>(T1);
- const DependentTemplateSpecializationType *Spec2 =
- cast<DependentTemplateSpecializationType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Spec1->getQualifier(),
- Spec2->getQualifier()))
- return false;
- if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
- Spec2->getIdentifier()))
- return false;
- if (Spec1->getNumArgs() != Spec2->getNumArgs())
- return false;
- for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context,
- Spec1->getArg(I), Spec2->getArg(I)))
- return false;
- }
- break;
- }
-
- case Type::PackExpansion:
- if (!IsStructurallyEquivalent(Context,
- cast<PackExpansionType>(T1)->getPattern(),
- cast<PackExpansionType>(T2)->getPattern()))
- return false;
- break;
-
- case Type::ObjCInterface: {
- const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1);
- const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Iface1->getDecl(), Iface2->getDecl()))
- return false;
- break;
- }
-
- case Type::ObjCObject: {
- const ObjCObjectType *Obj1 = cast<ObjCObjectType>(T1);
- const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Obj1->getBaseType(),
- Obj2->getBaseType()))
- return false;
- if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
- return false;
- for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context,
- Obj1->getProtocol(I),
- Obj2->getProtocol(I)))
- return false;
- }
- break;
- }
+ return Importer.getToContext().getBlockPointerType(ToPointeeType);
+}
- case Type::ObjCObjectPointer: {
- const ObjCObjectPointerType *Ptr1 = cast<ObjCObjectPointerType>(T1);
- const ObjCObjectPointerType *Ptr2 = cast<ObjCObjectPointerType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Ptr1->getPointeeType(),
- Ptr2->getPointeeType()))
- return false;
- break;
- }
+QualType
+ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) {
+ // FIXME: Check for C++ support in "to" context.
+ QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getLValueReferenceType(ToPointeeType);
+}
- case Type::Atomic: {
- if (!IsStructurallyEquivalent(Context,
- cast<AtomicType>(T1)->getValueType(),
- cast<AtomicType>(T2)->getValueType()))
- return false;
- break;
- }
+QualType
+ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) {
+ // FIXME: Check for C++0x support in "to" context.
+ QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getRValueReferenceType(ToPointeeType);
+}
- } // end switch
+QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
+ // FIXME: Check for C++ support in "to" context.
+ QualType ToPointeeType = Importer.Import(T->getPointeeType());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ QualType ClassType = Importer.Import(QualType(T->getClass(), 0));
+ return Importer.getToContext().getMemberPointerType(ToPointeeType,
+ ClassType.getTypePtr());
+}
- return true;
+QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getConstantArrayType(ToElementType,
+ T->getSize(),
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers());
}
-/// \brief Determine structural equivalence of two fields.
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- FieldDecl *Field1, FieldDecl *Field2) {
- RecordDecl *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
+QualType
+ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getIncompleteArrayType(ToElementType,
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers());
+}
- // For anonymous structs/unions, match up the anonymous struct/union type
- // declarations directly, so that we don't go off searching for anonymous
- // types
- if (Field1->isAnonymousStructOrUnion() &&
- Field2->isAnonymousStructOrUnion()) {
- RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
- RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
- return IsStructurallyEquivalent(Context, D1, D2);
- }
-
- // Check for equivalent field names.
- IdentifierInfo *Name1 = Field1->getIdentifier();
- IdentifierInfo *Name2 = Field2->getIdentifier();
- if (!::IsStructurallyEquivalent(Name1, Name2))
- return false;
+QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
- if (!IsStructurallyEquivalent(Context,
- Field1->getType(), Field2->getType())) {
- if (Context.Complain) {
- Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(Owner2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_field)
- << Field2->getDeclName() << Field2->getType();
- Context.Diag1(Field1->getLocation(), diag::note_odr_field)
- << Field1->getDeclName() << Field1->getType();
- }
- return false;
- }
+ Expr *Size = Importer.Import(T->getSizeExpr());
+ if (!Size)
+ return QualType();
- if (Field1->isBitField() != Field2->isBitField()) {
- if (Context.Complain) {
- Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(Owner2);
- if (Field1->isBitField()) {
- Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
- << Field1->getDeclName() << Field1->getType()
- << Field1->getBitWidthValue(Context.C1);
- Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field)
- << Field2->getDeclName();
- } else {
- Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
- << Field2->getDeclName() << Field2->getType()
- << Field2->getBitWidthValue(Context.C2);
- Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field)
- << Field1->getDeclName();
- }
- }
- return false;
- }
+ SourceRange Brackets = Importer.Import(T->getBracketsRange());
+ return Importer.getToContext().getVariableArrayType(ToElementType, Size,
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers(),
+ Brackets);
+}
+
+QualType ASTNodeImporter::VisitVectorType(const VectorType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
- if (Field1->isBitField()) {
- // Make sure that the bit-fields are the same length.
- unsigned Bits1 = Field1->getBitWidthValue(Context.C1);
- unsigned Bits2 = Field2->getBitWidthValue(Context.C2);
-
- if (Bits1 != Bits2) {
- if (Context.Complain) {
- Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(Owner2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
- << Field2->getDeclName() << Field2->getType() << Bits2;
- Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
- << Field1->getDeclName() << Field1->getType() << Bits1;
- }
- return false;
- }
- }
+ return Importer.getToContext().getVectorType(ToElementType,
+ T->getNumElements(),
+ T->getVectorKind());
+}
- return true;
+QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getExtVectorType(ToElementType,
+ T->getNumElements());
}
-/// \brief Find the index of the given anonymous struct/union within its
-/// context.
-///
-/// \returns Returns the index of this anonymous struct/union in its context,
-/// including the next assigned index (if none of them match). Returns an
-/// empty option if the context is not a record, i.e.. if the anonymous
-/// struct/union is at namespace or block scope.
-static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) {
- ASTContext &Context = Anon->getASTContext();
- QualType AnonTy = Context.getRecordType(Anon);
+QualType
+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 QualType();
- RecordDecl *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
- if (!Owner)
- return None;
+ return Importer.getToContext().getFunctionNoProtoType(ToResultType,
+ T->getExtInfo());
+}
- unsigned Index = 0;
- for (const auto *D : Owner->noload_decls()) {
- const auto *F = dyn_cast<FieldDecl>(D);
- if (!F || !F->isAnonymousStructOrUnion())
- continue;
-
- if (Context.hasSameType(F->getType(), AnonTy))
- break;
-
- ++Index;
+QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
+ QualType ToResultType = Importer.Import(T->getReturnType());
+ if (ToResultType.isNull())
+ return QualType();
+
+ // Import argument types
+ SmallVector<QualType, 4> ArgTypes;
+ for (const auto &A : T->param_types()) {
+ QualType ArgType = Importer.Import(A);
+ if (ArgType.isNull())
+ return QualType();
+ ArgTypes.push_back(ArgType);
}
-
- return Index;
-}
-
-/// \brief Determine structural equivalence of two records.
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- RecordDecl *D1, RecordDecl *D2) {
- if (D1->isUnion() != D2->isUnion()) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
- << D1->getDeclName() << (unsigned)D1->getTagKind();
- }
- return false;
+
+ // Import exception types
+ SmallVector<QualType, 4> ExceptionTypes;
+ for (const auto &E : T->exceptions()) {
+ QualType ExceptionType = Importer.Import(E);
+ if (ExceptionType.isNull())
+ return QualType();
+ ExceptionTypes.push_back(ExceptionType);
}
- if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) {
- // If both anonymous structs/unions are in a record context, make sure
- // they occur in the same location in the context records.
- if (Optional<unsigned> Index1 = findAnonymousStructOrUnionIndex(D1)) {
- if (Optional<unsigned> Index2 = findAnonymousStructOrUnionIndex(D2)) {
- if (*Index1 != *Index2)
- return false;
- }
- }
- }
+ FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo();
+ FunctionProtoType::ExtProtoInfo ToEPI;
- // If both declarations are class template specializations, we know
- // the ODR applies, so check the template and template arguments.
- ClassTemplateSpecializationDecl *Spec1
- = dyn_cast<ClassTemplateSpecializationDecl>(D1);
- ClassTemplateSpecializationDecl *Spec2
- = dyn_cast<ClassTemplateSpecializationDecl>(D2);
- if (Spec1 && Spec2) {
- // Check that the specialized templates are the same.
- if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(),
- Spec2->getSpecializedTemplate()))
- return false;
-
- // Check that the template arguments are the same.
- if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
- return false;
-
- for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
- if (!IsStructurallyEquivalent(Context,
- Spec1->getTemplateArgs().get(I),
- Spec2->getTemplateArgs().get(I)))
- return false;
- }
- // If one is a class template specialization and the other is not, these
- // structures are different.
- else if (Spec1 || Spec2)
- return false;
+ ToEPI.ExtInfo = FromEPI.ExtInfo;
+ ToEPI.Variadic = FromEPI.Variadic;
+ ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn;
+ ToEPI.TypeQuals = FromEPI.TypeQuals;
+ 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));
- // Compare the definitions of these two records. If either or both are
- // incomplete, we assume that they are equivalent.
- D1 = D1->getDefinition();
- D2 = D2->getDefinition();
- if (!D1 || !D2)
- return true;
-
- if (CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
- if (CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
- if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
- << D2CXX->getNumBases();
- Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
- << D1CXX->getNumBases();
- }
- return false;
- }
-
- // Check the base classes.
- for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
- BaseEnd1 = D1CXX->bases_end(),
- Base2 = D2CXX->bases_begin();
- Base1 != BaseEnd1;
- ++Base1, ++Base2) {
- if (!IsStructurallyEquivalent(Context,
- Base1->getType(), Base2->getType())) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(Base2->getLocStart(), diag::note_odr_base)
- << Base2->getType()
- << Base2->getSourceRange();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
- << Base1->getType()
- << Base1->getSourceRange();
- }
- return false;
- }
-
- // Check virtual vs. non-virtual inheritance mismatch.
- if (Base1->isVirtual() != Base2->isVirtual()) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(Base2->getLocStart(),
- diag::note_odr_virtual_base)
- << Base2->isVirtual() << Base2->getSourceRange();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
- << Base1->isVirtual()
- << Base1->getSourceRange();
- }
- return false;
- }
- }
- } else if (D1CXX->getNumBases() > 0) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
- << Base1->getType()
- << Base1->getSourceRange();
- Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
- }
- return false;
- }
- }
-
- // Check the fields for consistency.
- RecordDecl::field_iterator Field2 = D2->field_begin(),
- Field2End = D2->field_end();
- for (RecordDecl::field_iterator Field1 = D1->field_begin(),
- Field1End = D1->field_end();
- Field1 != Field1End;
- ++Field1, ++Field2) {
- if (Field2 == Field2End) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag1(Field1->getLocation(), diag::note_odr_field)
- << Field1->getDeclName() << Field1->getType();
- Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
- }
- return false;
- }
-
- if (!IsStructurallyEquivalent(Context, *Field1, *Field2))
- return false;
- }
-
- if (Field2 != Field2End) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_field)
- << Field2->getDeclName() << Field2->getType();
- Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
- }
- return false;
- }
-
- return true;
+ return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI);
}
-
-/// \brief Determine structural equivalence of two enums.
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- EnumDecl *D1, EnumDecl *D2) {
- EnumDecl::enumerator_iterator EC2 = D2->enumerator_begin(),
- EC2End = D2->enumerator_end();
- for (EnumDecl::enumerator_iterator EC1 = D1->enumerator_begin(),
- EC1End = D1->enumerator_end();
- EC1 != EC1End; ++EC1, ++EC2) {
- if (EC2 == EC2End) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
- << EC1->getDeclName()
- << EC1->getInitVal().toString(10);
- Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
- }
- return false;
- }
-
- llvm::APSInt Val1 = EC1->getInitVal();
- llvm::APSInt Val2 = EC2->getInitVal();
- if (!llvm::APSInt::isSameValue(Val1, Val2) ||
- !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
- << EC2->getDeclName()
- << EC2->getInitVal().toString(10);
- Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
- << EC1->getDeclName()
- << EC1->getInitVal().toString(10);
- }
- return false;
- }
- }
-
- if (EC2 != EC2End) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
- << EC2->getDeclName()
- << EC2->getInitVal().toString(10);
- Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
- }
- return false;
- }
-
- return true;
-}
-
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- TemplateParameterList *Params1,
- TemplateParameterList *Params2) {
- if (Params1->size() != Params2->size()) {
- if (Context.Complain) {
- Context.Diag2(Params2->getTemplateLoc(),
- diag::err_odr_different_num_template_parameters)
- << Params1->size() << Params2->size();
- Context.Diag1(Params1->getTemplateLoc(),
- diag::note_odr_template_parameter_list);
- }
- return false;
- }
-
- for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
- if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) {
- if (Context.Complain) {
- Context.Diag2(Params2->getParam(I)->getLocation(),
- diag::err_odr_different_template_parameter_kind);
- Context.Diag1(Params1->getParam(I)->getLocation(),
- diag::note_odr_template_parameter_here);
- }
- return false;
- }
-
- if (!Context.IsStructurallyEquivalent(Params1->getParam(I),
- Params2->getParam(I))) {
-
- return false;
- }
- }
-
- return true;
-}
-
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- TemplateTypeParmDecl *D1,
- TemplateTypeParmDecl *D2) {
- if (D1->isParameterPack() != D2->isParameterPack()) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
- << D2->isParameterPack();
- Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
- << D1->isParameterPack();
- }
- return false;
- }
-
- return true;
-}
-
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- NonTypeTemplateParmDecl *D1,
- NonTypeTemplateParmDecl *D2) {
- if (D1->isParameterPack() != D2->isParameterPack()) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
- << D2->isParameterPack();
- Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
- << D1->isParameterPack();
- }
- return false;
- }
-
- // Check types.
- if (!Context.IsStructurallyEquivalent(D1->getType(), D2->getType())) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(),
- diag::err_odr_non_type_parameter_type_inconsistent)
- << D2->getType() << D1->getType();
- Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
- << D1->getType();
- }
- return false;
- }
-
- return true;
-}
-
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- TemplateTemplateParmDecl *D1,
- TemplateTemplateParmDecl *D2) {
- if (D1->isParameterPack() != D2->isParameterPack()) {
- if (Context.Complain) {
- Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
- << D2->isParameterPack();
- Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
- << D1->isParameterPack();
- }
- return false;
- }
- // Check template parameter lists.
- return IsStructurallyEquivalent(Context, D1->getTemplateParameters(),
- D2->getTemplateParameters());
+QualType ASTNodeImporter::VisitParenType(const ParenType *T) {
+ QualType ToInnerType = Importer.Import(T->getInnerType());
+ if (ToInnerType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getParenType(ToInnerType);
}
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- ClassTemplateDecl *D1,
- ClassTemplateDecl *D2) {
- // Check template parameters.
- if (!IsStructurallyEquivalent(Context,
- D1->getTemplateParameters(),
- D2->getTemplateParameters()))
- return false;
+QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
+ TypedefNameDecl *ToDecl
+ = dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl()));
+ if (!ToDecl)
+ return QualType();
- // Check the templated declaration.
- return Context.IsStructurallyEquivalent(D1->getTemplatedDecl(),
- D2->getTemplatedDecl());
+ return Importer.getToContext().getTypeDeclType(ToDecl);
}
-/// \brief Determine structural equivalence of two declarations.
-static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- Decl *D1, Decl *D2) {
- // FIXME: Check for known structural equivalences via a callback of some sort.
-
- // Check whether we already know that these two declarations are not
- // structurally equivalent.
- if (Context.NonEquivalentDecls.count(std::make_pair(D1->getCanonicalDecl(),
- D2->getCanonicalDecl())))
- return false;
-
- // Determine whether we've already produced a tentative equivalence for D1.
- Decl *&EquivToD1 = Context.TentativeEquivalences[D1->getCanonicalDecl()];
- if (EquivToD1)
- return EquivToD1 == D2->getCanonicalDecl();
+QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
+ Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
+ if (!ToExpr)
+ return QualType();
- // Produce a tentative equivalence D1 <-> D2, which will be checked later.
- EquivToD1 = D2->getCanonicalDecl();
- Context.DeclsToCheck.push_back(D1->getCanonicalDecl());
- return true;
+ return Importer.getToContext().getTypeOfExprType(ToExpr);
}
-bool StructuralEquivalenceContext::IsStructurallyEquivalent(Decl *D1,
- Decl *D2) {
- if (!::IsStructurallyEquivalent(*this, D1, D2))
- return false;
+QualType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
+ QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
+ if (ToUnderlyingType.isNull())
+ return QualType();
- return !Finish();
+ return Importer.getToContext().getTypeOfType(ToUnderlyingType);
}
-bool StructuralEquivalenceContext::IsStructurallyEquivalent(QualType T1,
- QualType T2) {
- if (!::IsStructurallyEquivalent(*this, T1, T2))
- return false;
+QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
+ // FIXME: Make sure that the "to" context supports C++0x!
+ Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
+ if (!ToExpr)
+ return QualType();
- return !Finish();
+ QualType UnderlyingType = Importer.Import(T->getUnderlyingType());
+ if (UnderlyingType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getDecltypeType(ToExpr, UnderlyingType);
}
-bool StructuralEquivalenceContext::Finish() {
- while (!DeclsToCheck.empty()) {
- // Check the next declaration.
- Decl *D1 = DeclsToCheck.front();
- DeclsToCheck.pop_front();
-
- 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 (RecordDecl *Record1 = dyn_cast<RecordDecl>(D1)) {
- if (RecordDecl *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 (EnumDecl *Enum1 = dyn_cast<EnumDecl>(D1)) {
- if (EnumDecl *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 (TypedefNameDecl *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) {
- if (TypedefNameDecl *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 (ClassTemplateDecl *ClassTemplate1
- = dyn_cast<ClassTemplateDecl>(D1)) {
- if (ClassTemplateDecl *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) {
- if (!::IsStructurallyEquivalent(ClassTemplate1->getIdentifier(),
- ClassTemplate2->getIdentifier()) ||
- !::IsStructurallyEquivalent(*this, ClassTemplate1, ClassTemplate2))
- Equivalent = false;
- } else {
- // Class template/non-class-template mismatch.
- Equivalent = false;
- }
- } else if (TemplateTypeParmDecl *TTP1= dyn_cast<TemplateTypeParmDecl>(D1)) {
- if (TemplateTypeParmDecl *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- } else if (NonTypeTemplateParmDecl *NTTP1
- = dyn_cast<NonTypeTemplateParmDecl>(D1)) {
- if (NonTypeTemplateParmDecl *NTTP2
- = dyn_cast<NonTypeTemplateParmDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- } else if (TemplateTemplateParmDecl *TTP1
- = dyn_cast<TemplateTemplateParmDecl>(D1)) {
- if (TemplateTemplateParmDecl *TTP2
- = dyn_cast<TemplateTemplateParmDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- }
-
- if (!Equivalent) {
- // Note that these two declarations are not equivalent (and we already
- // know about it).
- NonEquivalentDecls.insert(std::make_pair(D1->getCanonicalDecl(),
- D2->getCanonicalDecl()));
- return true;
- }
- // FIXME: Check other declaration kinds!
+QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
+ QualType ToBaseType = Importer.Import(T->getBaseType());
+ QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
+ if (ToBaseType.isNull() || ToUnderlyingType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getUnaryTransformType(ToBaseType,
+ ToUnderlyingType,
+ T->getUTTKind());
+}
+
+QualType 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 QualType();
}
- return false;
+ return Importer.getToContext().getAutoType(ToDeduced, T->getKeyword(),
+ /*IsDependent*/false);
}
-//----------------------------------------------------------------------------
-// Import Types
-//----------------------------------------------------------------------------
+QualType ASTNodeImporter::VisitInjectedClassNameType(
+ const InjectedClassNameType *T) {
+ CXXRecordDecl *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl()));
+ if (!D)
+ return QualType();
-QualType ASTNodeImporter::VisitType(const Type *T) {
- Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
- << T->getTypeClassName();
- return QualType();
+ QualType InjType = Importer.Import(T->getInjectedSpecializationType());
+ if (InjType.isNull())
+ return QualType();
+
+ // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading
+ // See comments in InjectedClassNameType definition for details
+ // return Importer.getToContext().getInjectedClassNameType(D, InjType);
+ enum {
+ TypeAlignmentInBits = 4,
+ TypeAlignment = 1 << TypeAlignmentInBits
+ };
+
+ return QualType(new (Importer.getToContext(), TypeAlignment)
+ InjectedClassNameType(D, InjType), 0);
}
-QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
- switch (T->getKind()) {
-#define SHARED_SINGLETON_TYPE(Expansion)
-#define BUILTIN_TYPE(Id, SingletonId) \
- case BuiltinType::Id: return Importer.getToContext().SingletonId;
-#include "clang/AST/BuiltinTypes.def"
+QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
+ RecordDecl *ToDecl
+ = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl()));
+ if (!ToDecl)
+ return QualType();
- // FIXME: for Char16, Char32, and NullPtr, make sure that the "to"
- // context supports C++.
+ return Importer.getToContext().getTagDeclType(ToDecl);
+}
- // FIXME: for ObjCId, ObjCClass, and ObjCSel, make sure that the "to"
- // context supports ObjC.
+QualType ASTNodeImporter::VisitEnumType(const EnumType *T) {
+ EnumDecl *ToDecl
+ = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl()));
+ if (!ToDecl)
+ return QualType();
- case BuiltinType::Char_U:
- // The context we're importing from has an unsigned 'char'. If we're
- // importing into a context with a signed 'char', translate to
- // 'unsigned char' instead.
- if (Importer.getToContext().getLangOpts().CharIsSigned)
- return Importer.getToContext().UnsignedCharTy;
-
- return Importer.getToContext().CharTy;
+ return Importer.getToContext().getTagDeclType(ToDecl);
+}
- case BuiltinType::Char_S:
- // The context we're importing from has an unsigned 'char'. If we're
- // importing into a context with a signed 'char', translate to
- // 'unsigned char' instead.
- if (!Importer.getToContext().getLangOpts().CharIsSigned)
- return Importer.getToContext().SignedCharTy;
-
- return Importer.getToContext().CharTy;
+QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
+ QualType FromModifiedType = T->getModifiedType();
+ QualType FromEquivalentType = T->getEquivalentType();
+ QualType ToModifiedType;
+ QualType ToEquivalentType;
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U:
- // FIXME: If not in C++, shall we translate to the C equivalent of
- // wchar_t?
- return Importer.getToContext().WCharTy;
+ if (!FromModifiedType.isNull()) {
+ ToModifiedType = Importer.Import(FromModifiedType);
+ if (ToModifiedType.isNull())
+ return QualType();
+ }
+ if (!FromEquivalentType.isNull()) {
+ ToEquivalentType = Importer.Import(FromEquivalentType);
+ if (ToEquivalentType.isNull())
+ return QualType();
}
- llvm_unreachable("Invalid BuiltinType Kind!");
+ return Importer.getToContext().getAttributedType(T->getAttrKind(),
+ ToModifiedType, ToEquivalentType);
}
-QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getComplexType(ToElementType);
-}
-
-QualType ASTNodeImporter::VisitPointerType(const PointerType *T) {
- QualType ToPointeeType = Importer.Import(T->getPointeeType());
- if (ToPointeeType.isNull())
- return QualType();
-
- return Importer.getToContext().getPointerType(ToPointeeType);
-}
-
-QualType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) {
- // FIXME: Check for blocks support in "to" context.
- QualType ToPointeeType = Importer.Import(T->getPointeeType());
- if (ToPointeeType.isNull())
- return QualType();
-
- return Importer.getToContext().getBlockPointerType(ToPointeeType);
-}
-
-QualType
-ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) {
- // FIXME: Check for C++ support in "to" context.
- QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
- if (ToPointeeType.isNull())
- return QualType();
-
- return Importer.getToContext().getLValueReferenceType(ToPointeeType);
-}
-
-QualType
-ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) {
- // FIXME: Check for C++0x support in "to" context.
- QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
- if (ToPointeeType.isNull())
- return QualType();
-
- return Importer.getToContext().getRValueReferenceType(ToPointeeType);
-}
-
-QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
- // FIXME: Check for C++ support in "to" context.
- QualType ToPointeeType = Importer.Import(T->getPointeeType());
- if (ToPointeeType.isNull())
- return QualType();
-
- QualType ClassType = Importer.Import(QualType(T->getClass(), 0));
- return Importer.getToContext().getMemberPointerType(ToPointeeType,
- ClassType.getTypePtr());
-}
-
-QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getConstantArrayType(ToElementType,
- T->getSize(),
- T->getSizeModifier(),
- T->getIndexTypeCVRQualifiers());
-}
-
-QualType
-ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getIncompleteArrayType(ToElementType,
- T->getSizeModifier(),
- T->getIndexTypeCVRQualifiers());
-}
-
-QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return QualType();
-
- Expr *Size = Importer.Import(T->getSizeExpr());
- if (!Size)
- return QualType();
-
- SourceRange Brackets = Importer.Import(T->getBracketsRange());
- return Importer.getToContext().getVariableArrayType(ToElementType, Size,
- T->getSizeModifier(),
- T->getIndexTypeCVRQualifiers(),
- Brackets);
-}
-
-QualType ASTNodeImporter::VisitVectorType(const VectorType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getVectorType(ToElementType,
- T->getNumElements(),
- T->getVectorKind());
-}
-
-QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return QualType();
-
- return Importer.getToContext().getExtVectorType(ToElementType,
- T->getNumElements());
-}
-
-QualType
-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 QualType();
-
- return Importer.getToContext().getFunctionNoProtoType(ToResultType,
- T->getExtInfo());
-}
-
-QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
- QualType ToResultType = Importer.Import(T->getReturnType());
- if (ToResultType.isNull())
- return QualType();
-
- // Import argument types
- SmallVector<QualType, 4> ArgTypes;
- for (const auto &A : T->param_types()) {
- QualType ArgType = Importer.Import(A);
- if (ArgType.isNull())
- return QualType();
- ArgTypes.push_back(ArgType);
- }
-
- // Import exception types
- SmallVector<QualType, 4> ExceptionTypes;
- for (const auto &E : T->exceptions()) {
- QualType ExceptionType = Importer.Import(E);
- if (ExceptionType.isNull())
- return QualType();
- ExceptionTypes.push_back(ExceptionType);
- }
-
- FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo();
- FunctionProtoType::ExtProtoInfo ToEPI;
-
- ToEPI.ExtInfo = FromEPI.ExtInfo;
- ToEPI.Variadic = FromEPI.Variadic;
- ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn;
- ToEPI.TypeQuals = FromEPI.TypeQuals;
- 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));
-
- return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI);
-}
-
-QualType ASTNodeImporter::VisitParenType(const ParenType *T) {
- QualType ToInnerType = Importer.Import(T->getInnerType());
- if (ToInnerType.isNull())
- return QualType();
-
- return Importer.getToContext().getParenType(ToInnerType);
-}
-
-QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
- TypedefNameDecl *ToDecl
- = dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl()));
- if (!ToDecl)
- return QualType();
-
- return Importer.getToContext().getTypeDeclType(ToDecl);
-}
-
-QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
- Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
- if (!ToExpr)
- return QualType();
-
- return Importer.getToContext().getTypeOfExprType(ToExpr);
-}
-
-QualType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
- QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
- if (ToUnderlyingType.isNull())
- return QualType();
-
- return Importer.getToContext().getTypeOfType(ToUnderlyingType);
-}
-
-QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
- // FIXME: Make sure that the "to" context supports C++0x!
- Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
- if (!ToExpr)
- return QualType();
-
- QualType UnderlyingType = Importer.Import(T->getUnderlyingType());
- if (UnderlyingType.isNull())
- return QualType();
-
- return Importer.getToContext().getDecltypeType(ToExpr, UnderlyingType);
-}
-QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
- QualType ToBaseType = Importer.Import(T->getBaseType());
- QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
- if (ToBaseType.isNull() || ToUnderlyingType.isNull())
+QualType ASTNodeImporter::VisitTemplateTypeParmType(
+ const TemplateTypeParmType *T) {
+ TemplateTypeParmDecl *ParmDecl =
+ cast_or_null<TemplateTypeParmDecl>(Importer.Import(T->getDecl()));
+ if (!ParmDecl && T->getDecl())
return QualType();
- return Importer.getToContext().getUnaryTransformType(ToBaseType,
- ToUnderlyingType,
- T->getUTTKind());
-}
-
-QualType 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 QualType();
- }
-
- return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(),
- /*IsDependent*/false);
+ return Importer.getToContext().getTemplateTypeParmType(
+ T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl);
}
-QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
- RecordDecl *ToDecl
- = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl()));
- if (!ToDecl)
+QualType ASTNodeImporter::VisitSubstTemplateTypeParmType(
+ const SubstTemplateTypeParmType *T) {
+ const TemplateTypeParmType *Replaced =
+ cast_or_null<TemplateTypeParmType>(Importer.Import(
+ QualType(T->getReplacedParameter(), 0)).getTypePtr());
+ if (!Replaced)
return QualType();
- return Importer.getToContext().getTagDeclType(ToDecl);
-}
-
-QualType ASTNodeImporter::VisitEnumType(const EnumType *T) {
- EnumDecl *ToDecl
- = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl()));
- if (!ToDecl)
+ QualType Replacement = Importer.Import(T->getReplacementType());
+ if (Replacement.isNull())
return QualType();
+ Replacement = Replacement.getCanonicalType();
- return Importer.getToContext().getTagDeclType(ToDecl);
+ return Importer.getToContext().getSubstTemplateTypeParmType(
+ Replaced, Replacement);
}
QualType ASTNodeImporter::VisitTemplateSpecializationType(
return QualType();
}
return Importer.getToContext().getTemplateSpecializationType(ToTemplate,
- ToTemplateArgs.data(),
- ToTemplateArgs.size(),
+ ToTemplateArgs,
ToCanonType);
}
if (ToBaseType.isNull())
return QualType();
+ SmallVector<QualType, 4> TypeArgs;
+ for (auto TypeArg : T->getTypeArgsAsWritten()) {
+ QualType ImportedTypeArg = Importer.Import(TypeArg);
+ if (ImportedTypeArg.isNull())
+ return QualType();
+
+ TypeArgs.push_back(ImportedTypeArg);
+ }
+
SmallVector<ObjCProtocolDecl *, 4> Protocols;
for (auto *P : T->quals()) {
ObjCProtocolDecl *Protocol
Protocols.push_back(Protocol);
}
- return Importer.getToContext().getObjCObjectType(ToBaseType,
- Protocols.data(),
- Protocols.size());
+ return Importer.getToContext().getObjCObjectType(ToBaseType, TypeArgs,
+ Protocols,
+ T->isKindOfTypeAsWritten());
}
QualType
bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC,
DeclarationName &Name,
+ NamedDecl *&ToD,
SourceLocation &Loc) {
// Import the context of this declaration.
DC = Importer.ImportContext(D->getDeclContext());
// Import the location of this declaration.
Loc = Importer.Import(D->getLocation());
+ ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D));
return false;
}
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::CXXUsingDirective:
+ case DeclarationName::CXXDeductionGuideName:
return;
case DeclarationName::CXXOperatorName: {
ToData.HasInClassInitializer = FromData.HasInClassInitializer;
ToData.HasUninitializedReferenceMember
= FromData.HasUninitializedReferenceMember;
+ ToData.HasUninitializedFields = FromData.HasUninitializedFields;
+ ToData.HasInheritedConstructor = FromData.HasInheritedConstructor;
+ ToData.HasInheritedAssignment = FromData.HasInheritedAssignment;
ToData.NeedOverloadResolutionForMoveConstructor
= FromData.NeedOverloadResolutionForMoveConstructor;
ToData.NeedOverloadResolutionForMoveAssignment
ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor;
ToData.HasConstexprNonCopyMoveConstructor
= FromData.HasConstexprNonCopyMoveConstructor;
+ ToData.HasDefaultedDefaultConstructor
+ = FromData.HasDefaultedDefaultConstructor;
ToData.DefaultedDefaultConstructorIsConstexpr
= FromData.DefaultedDefaultConstructorIsConstexpr;
ToData.HasConstexprDefaultConstructor
ToData.UserProvidedDefaultConstructor
= FromData.UserProvidedDefaultConstructor;
ToData.DeclaredSpecialMembers = FromData.DeclaredSpecialMembers;
- ToData.ImplicitCopyConstructorHasConstParam
- = FromData.ImplicitCopyConstructorHasConstParam;
+ ToData.ImplicitCopyConstructorCanHaveConstParamForVBase
+ = FromData.ImplicitCopyConstructorCanHaveConstParamForVBase;
+ ToData.ImplicitCopyConstructorCanHaveConstParamForNonVBase
+ = FromData.ImplicitCopyConstructorCanHaveConstParamForNonVBase;
ToData.ImplicitCopyAssignmentHasConstParam
= FromData.ImplicitCopyAssignmentHasConstParam;
ToData.HasDeclaredCopyConstructorWithConstParam
bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To,
ImportDefinitionKind Kind) {
- if (To->getDefinition())
+ if (To->getAnyInitializer())
return false;
// FIXME: Can we really import any initializer? Alternatively, we could force
TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
TemplateParameterList *Params) {
- SmallVector<NamedDecl *, 4> ToParams;
- ToParams.reserve(Params->size());
- for (TemplateParameterList::iterator P = Params->begin(),
- PEnd = Params->end();
- P != PEnd; ++P) {
- Decl *To = Importer.Import(*P);
- if (!To)
+ SmallVector<NamedDecl *, 4> ToParams(Params->size());
+ if (ImportContainerChecked(*Params, ToParams))
+ return nullptr;
+
+ Expr *ToRequiresClause;
+ if (Expr *const R = Params->getRequiresClause()) {
+ ToRequiresClause = Importer.Import(R);
+ if (!ToRequiresClause)
return nullptr;
-
- ToParams.push_back(cast<NamedDecl>(To));
+ } else {
+ ToRequiresClause = nullptr;
}
-
+
return TemplateParameterList::Create(Importer.getToContext(),
Importer.Import(Params->getTemplateLoc()),
Importer.Import(Params->getLAngleLoc()),
- ToParams.data(), ToParams.size(),
- Importer.Import(Params->getRAngleLoc()));
+ ToParams,
+ Importer.Import(Params->getRAngleLoc()),
+ ToRequiresClause);
}
TemplateArgument
}
case TemplateArgument::Declaration: {
- ValueDecl *FromD = From.getAsDecl();
- if (ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(FromD)))
- return TemplateArgument(To, From.isDeclForReferenceParam());
- return TemplateArgument();
+ ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl()));
+ QualType ToType = Importer.Import(From.getParamTypeForDecl());
+ if (!To || ToType.isNull())
+ return TemplateArgument();
+ return TemplateArgument(To, ToType);
}
case TemplateArgument::NullPtr: {
ToPack.reserve(From.pack_size());
if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack))
return TemplateArgument();
-
- TemplateArgument *ToArgs
- = new (Importer.getToContext()) TemplateArgument[ToPack.size()];
- std::copy(ToPack.begin(), ToPack.end(), ToArgs);
- return TemplateArgument(ToArgs, ToPack.size());
+
+ return TemplateArgument(
+ llvm::makeArrayRef(ToPack).copy(Importer.getToContext()));
}
}
llvm_unreachable("Invalid template argument kind");
}
+TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc(
+ const TemplateArgumentLoc &TALoc, bool &Error) {
+ Error = false;
+ 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)
+ Error = true;
+ } else if (Arg.getKind() == TemplateArgument::Type) {
+ if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo()))
+ ToInfo = TemplateArgumentLocInfo(TSI);
+ else
+ Error = true;
+ } else {
+ ToInfo = TemplateArgumentLocInfo(
+ Importer.Import(FromInfo.getTemplateQualifierLoc()),
+ Importer.Import(FromInfo.getTemplateNameLoc()),
+ Importer.Import(FromInfo.getTemplateEllipsisLoc()));
+ }
+ return TemplateArgumentLoc(Arg, ToInfo);
+}
+
bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs) {
StructuralEquivalenceContext Ctx(Importer.getFromContext(),
Importer.getToContext(),
Importer.getNonEquivalentDecls());
- return Ctx.IsStructurallyEquivalent(From, To);
+ return Ctx.IsStructurallyEquivalent(From, To);
}
bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From,
return ToD;
}
+Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
+
+ SourceLocation Loc = Importer.Import(D->getLocation());
+ SourceLocation ColonLoc = Importer.Import(D->getColonLoc());
+
+ // Import the context of this declaration.
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ if (!DC)
+ return nullptr;
+
+ AccessSpecDecl *accessSpecDecl
+ = AccessSpecDecl::Create(Importer.getToContext(), D->getAccess(),
+ DC, Loc, ColonLoc);
+
+ if (!accessSpecDecl)
+ return nullptr;
+
+ // Lexical DeclContext and Semantic DeclContext
+ // is always the same for the accessSpec.
+ accessSpecDecl->setLexicalDeclContext(DC);
+ DC->addDeclInternal(accessSpecDecl);
+
+ return accessSpecDecl;
+}
+
+Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ if (!DC)
+ return nullptr;
+
+ 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();
+ StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg));
+ if (!ToMsg && FromMsg)
+ return nullptr;
+
+ StaticAssertDecl *ToD = StaticAssertDecl::Create(
+ Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
+ Importer.Import(D->getRParenLoc()), D->isFailed());
+
+ ToD->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToD);
+ Importer.Imported(D, ToD);
+ return ToD;
+}
+
Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
NamespaceDecl *MergeWithNamespace = nullptr;
if (!Name) {
} else {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace))
continue;
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// If this typedef is not in block scope, determine whether we've
// seen a typedef with the same name (that we can merge with) or any
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
FoundTypedef->getUnderlyingType()))
return Importer.Imported(D, FoundTypedef);
}
-
+
ConflictingDecls.push_back(FoundDecls[I]);
}
-
+
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
ConflictingDecls.data(),
return nullptr;
}
}
-
+
// Import the underlying type of this typedef;
QualType T = Importer.Import(D->getUnderlyingType());
if (T.isNull())
StartL, Loc,
Name.getAsIdentifierInfo(),
TInfo);
-
+
ToTypedef->setAccess(D->getAccess());
ToTypedef->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToTypedef);
LexicalDC->addDeclInternal(ToTypedef);
-
+
return ToTypedef;
}
return VisitTypedefNameDecl(D, /*IsAlias=*/true);
}
+Decl *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 (ToD)
+ return ToD;
+
+ assert(LexicalDC->isFunctionOrMethod());
+
+ LabelDecl *ToLabel = D->isGnuLocal()
+ ? LabelDecl::Create(Importer.getToContext(),
+ DC, Importer.Import(D->getLocation()),
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getLocStart()))
+ : LabelDecl::Create(Importer.getToContext(),
+ DC, Importer.Import(D->getLocation()),
+ Name.getAsIdentifierInfo());
+ Importer.Imported(D, ToLabel);
+
+ LabelStmt *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt()));
+ if (!Label)
+ return nullptr;
+
+ ToLabel->setStmt(Label);
+ ToLabel->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToLabel);
+ return ToLabel;
+}
+
Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
// Import the major distinguishing characteristics of this enum.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Figure out what enum name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
if (!DC->isFunctionOrMethod() && SearchName) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(SearchName, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Figure out what structure name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
// 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->localUncachedLookup(SearchName, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls);
+
+ if (!FoundDecls.empty()) {
+ // We're going to have to compare D against potentially conflicting Decls, so complete it.
+ if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition())
+ D->getASTContext().getExternalSource()->CompleteType(D);
+ }
+
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
FoundRecord->isAnonymousStructOrUnion()) {
// If both anonymous structs/unions are in a record context, make sure
// they occur in the same location in the context records.
- if (Optional<unsigned> Index1
- = findAnonymousStructOrUnionIndex(D)) {
- if (Optional<unsigned> Index2 =
- findAnonymousStructOrUnionIndex(FoundRecord)) {
+ if (Optional<unsigned> Index1 =
+ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(
+ D)) {
+ if (Optional<unsigned> Index2 = StructuralEquivalenceContext::
+ findUntaggedStructOrUnionIndex(FoundRecord)) {
if (*Index1 != *Index2)
continue;
}
}
}
+ PrevDecl = FoundRecord;
+
if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
if ((SearchName && !D->isCompleteDefinition())
|| (D->isCompleteDefinition() &&
RecordDecl *D2 = AdoptDecl;
SourceLocation StartLoc = Importer.Import(D->getLocStart());
if (!D2) {
- if (isa<CXXRecordDecl>(D)) {
- CXXRecordDecl *D2CXX = CXXRecordDecl::Create(Importer.getToContext(),
- D->getTagKind(),
- DC, StartLoc, Loc,
- Name.getAsIdentifierInfo());
+ CXXRecordDecl *D2CXX = nullptr;
+ if (CXXRecordDecl *DCXX = llvm::dyn_cast<CXXRecordDecl>(D)) {
+ if (DCXX->isLambda()) {
+ TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo());
+ D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(),
+ DC, TInfo, Loc,
+ DCXX->isDependentLambda(),
+ DCXX->isGenericLambda(),
+ DCXX->getLambdaCaptureDefault());
+ 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;
+ D2CXX = CXXRecordDecl::Create(
+ Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc,
+ Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation);
+ Importer.getToContext().getTypeDeclType(
+ D2CXX, llvm::dyn_cast<CXXRecordDecl>(DC));
+ } else {
+ D2CXX = CXXRecordDecl::Create(Importer.getToContext(),
+ D->getTagKind(),
+ DC, StartLoc, Loc,
+ Name.getAsIdentifierInfo());
+ }
D2 = D2CXX;
D2->setAccess(D->getAccess());
} else {
LexicalDC->addDeclInternal(D2);
if (D->isAnonymousStructOrUnion())
D2->setAnonymousStructOrUnion(true);
+ if (PrevDecl) {
+ // FIXME: do this for all Redeclarables, not just RecordDecls.
+ D2->setPreviousDecl(PrevDecl);
+ }
}
Importer.Imported(D, D2);
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
QualType T = Importer.Import(D->getType());
if (T.isNull())
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Try to find a function in our own ("to") context with the same name, same
// type, and in the same context as the function we're importing.
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
-
+
if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) {
if (FoundFunction->hasExternalFormalLinkage() &&
D->hasExternalFormalLinkage()) {
// FIXME: Actually try to merge the body and other attributes.
return Importer.Imported(D, FoundFunction);
}
-
+
// FIXME: Check for overloading more carefully, e.g., by boosting
// Sema::IsOverload out to the AST library.
-
+
// Function overloading is okay in C++.
if (Importer.getToContext().getLangOpts().CPlusPlus)
continue;
-
+
// Complain about inconsistent function types.
Importer.ToDiag(Loc, diag::err_odr_function_type_inconsistent)
<< Name << D->getType() << FoundFunction->getType();
<< FoundFunction->getType();
}
}
-
+
ConflictingDecls.push_back(FoundDecls[I]);
}
-
+
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
ConflictingDecls.data(),
// Import the function parameters.
SmallVector<ParmVarDecl *, 8> Parameters;
- for (auto P : D->params()) {
+ for (auto P : D->parameters()) {
ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P));
if (!ToP)
return nullptr;
// Create the imported function.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
FunctionDecl *ToFunction = nullptr;
+ SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart());
if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
FromConstructor->isExplicit(),
D->isInlineSpecified(),
D->isImplicit(),
D->isConstexpr());
+ if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
+ SmallVector<CXXCtorInitializer *, 4> CtorInitializers;
+ for (CXXCtorInitializer *I : FromConstructor->inits()) {
+ CXXCtorInitializer *ToI =
+ cast_or_null<CXXCtorInitializer>(Importer.Import(I));
+ if (!ToI && I)
+ return nullptr;
+ CtorInitializers.push_back(ToI);
+ }
+ CXXCtorInitializer **Memory =
+ new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
+ std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
+ CXXConstructorDecl *ToCtor = llvm::cast<CXXConstructorDecl>(ToFunction);
+ ToCtor->setCtorInitializers(Memory);
+ ToCtor->setNumCtorInitializers(NumInitializers);
+ }
} else if (isa<CXXDestructorDecl>(D)) {
ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
D->isInlineSpecified(),
D->isImplicit());
= dyn_cast<CXXConversionDecl>(D)) {
ToFunction = CXXConversionDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
D->isInlineSpecified(),
FromConversion->isExplicit(),
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
ToFunction = CXXMethodDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
Method->getStorageClass(),
Method->isInlineSpecified(),
Importer.Import(D->getLocEnd()));
} else {
ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo, D->getStorageClass(),
D->isInlineSpecified(),
D->hasWrittenPrototype(),
ToFunction->setType(T);
}
+ // Import the body, if any.
+ if (Stmt *FromBody = D->getBody()) {
+ if (Stmt *ToBody = Importer.Import(FromBody)) {
+ ToFunction->setBody(ToBody);
+ }
+ }
+
// FIXME: Other bits to merge?
// Add this function to the lexical context.
LexicalDC->addDeclInternal(ToFunction);
+ if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
+ ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod);
+
return ToFunction;
}
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) {
// For anonymous fields, match up by index.
if (!Name && getFieldIndex(D) != getFieldIndex(FoundField))
continue;
- if (Importer.IsStructurallyEquivalent(D->getType(),
+ if (Importer.IsStructurallyEquivalent(D->getType(),
FoundField->getType())) {
Importer.Imported(D, FoundField);
return FoundField;
}
-
+
Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent)
<< Name << D->getType() << FoundField->getType();
Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
D->getInClassInitStyle());
ToField->setAccess(D->getAccess());
ToField->setLexicalDeclContext(LexicalDC);
- if (ToField->hasInClassInitializer())
- ToField->setInClassInitializer(D->getInClassInitializer());
+ if (Expr *FromInitializer = D->getInClassInitializer()) {
+ Expr *ToInitializer = Importer.Import(FromInitializer);
+ if (ToInitializer)
+ ToField->setInClassInitializer(ToInitializer);
+ else
+ return nullptr;
+ }
ToField->setImplicit(D->isImplicit());
Importer.Imported(D, ToField);
LexicalDC->addDeclInternal(ToField);
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (IndirectFieldDecl *FoundField
= dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
if (!Name && getFieldIndex(D) != getFieldIndex(FoundField))
continue;
- if (Importer.IsStructurallyEquivalent(D->getType(),
+ if (Importer.IsStructurallyEquivalent(D->getType(),
FoundField->getType(),
!Name.isEmpty())) {
Importer.Imported(D, FoundField);
}
IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create(
- Importer.getToContext(), DC,
- Loc, Name.getAsIdentifierInfo(), T,
- NamedChain, D->getChainingSize());
+ Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T,
+ {NamedChain, D->getChainingSize()});
+
+ for (const auto *Attr : D->attrs())
+ ToIndirectField->addAttr(Attr->clone(Importer.getToContext()));
+
ToIndirectField->setAccess(D->getAccess());
ToIndirectField->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToIndirectField);
return ToIndirectField;
}
+Decl *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;
+
+ // Determine whether we've already imported this decl.
+ // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup.
+ auto *RD = cast<CXXRecordDecl>(DC);
+ FriendDecl *ImportedFriend = RD->getFirstFriend();
+ StructuralEquivalenceContext Context(
+ Importer.getFromContext(), Importer.getToContext(),
+ Importer.getNonEquivalentDecls(), false, false);
+
+ while (ImportedFriend) {
+ if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
+ if (Context.IsStructurallyEquivalent(D->getFriendDecl(),
+ ImportedFriend->getFriendDecl()))
+ return Importer.Imported(D, ImportedFriend);
+
+ } else if (D->getFriendType() && ImportedFriend->getFriendType()) {
+ if (Importer.IsStructurallyEquivalent(
+ D->getFriendType()->getType(),
+ ImportedFriend->getFriendType()->getType(), true))
+ return Importer.Imported(D, ImportedFriend);
+ }
+ ImportedFriend = ImportedFriend->getNextFriend();
+ }
+
+ // Not found. Create it.
+ FriendDecl::FriendUnion ToFU;
+ if (NamedDecl *FriendD = D->getFriendDecl())
+ ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD));
+ else
+ ToFU = Importer.Import(D->getFriendType());
+ if (!ToFU)
+ return nullptr;
+
+ SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
+ TemplateParameterList **FromTPLists =
+ D->getTrailingObjects<TemplateParameterList *>();
+ for (unsigned I = 0; I < D->NumTPLists; I++) {
+ TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]);
+ if (!List)
+ return nullptr;
+ ToTPLists[I] = List;
+ }
+
+ FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC,
+ Importer.Import(D->getLocation()),
+ ToFU, Importer.Import(D->getFriendLoc()),
+ ToTPLists);
+
+ Importer.Imported(D, FrD);
+ RD->pushFriendDecl(FrD);
+
+ FrD->setAccess(D->getAccess());
+ FrD->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(FrD);
+ return FrD;
+}
+
Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
// Import the major distinguishing characteristics of an ivar.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
- // Determine whether we've already imported this ivar
+ // Determine whether we've already imported this ivar
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) {
- if (Importer.IsStructurallyEquivalent(D->getType(),
+ if (Importer.IsStructurallyEquivalent(D->getType(),
FoundIvar->getType())) {
Importer.Imported(D, FoundIvar);
return FoundIvar;
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Try to find a variable in our own ("to") context with the same name and
// in the same context as the variable we're importing.
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
-
+
if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) {
// We have found a variable that we may need to merge with. Check it.
if (FoundVar->hasExternalFormalLinkage() &&
D->hasExternalFormalLinkage()) {
- if (Importer.IsStructurallyEquivalent(D->getType(),
+ if (Importer.IsStructurallyEquivalent(D->getType(),
FoundVar->getType())) {
MergeWithVar = FoundVar;
break;
Importer.Imported(D, ToVar);
LexicalDC->addDeclInternal(ToVar);
+ if (!D->isFileVarDecl() &&
+ D->isUsed())
+ ToVar->setIsUsed();
+
// Merge the initializer.
if (ImportDefinition(D, ToVar))
return nullptr;
+ if (D->isConstexpr())
+ ToVar->setConstexpr(true);
+
return ToVar;
}
return nullptr;
// Create the imported parameter.
- ImplicitParamDecl *ToParm
- = ImplicitParamDecl::Create(Importer.getToContext(), DC,
- Loc, Name.getAsIdentifierInfo(),
- T);
+ auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo(), T,
+ D->getParameterKind());
return Importer.Imported(D, ToParm);
}
Importer.Import(D->getInnerLocStart()),
Loc, Name.getAsIdentifierInfo(),
T, TInfo, D->getStorageClass(),
- /*FIXME: Default argument*/nullptr);
+ /*DefaultArg*/ nullptr);
+
+ // Set the default argument.
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);
+ } else if (D->hasUnparsedDefaultArg()) {
+ ToParm->setUnparsedDefaultArg();
+ } else if (D->hasDefaultArg()) {
+ FromDefArg = D->getDefaultArg();
+ ToDefArg = Importer.Import(FromDefArg);
+ ToParm->setDefaultArg(ToDefArg);
+ }
+ if (FromDefArg && !ToDefArg)
+ return nullptr;
+
+ if (D->isUsed())
+ ToParm->setIsUsed();
+
return Importer.Imported(D, ToParm);
}
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecls[I])) {
if (FoundMethod->isInstanceMethod() != D->isInstanceMethod())
}
// Check parameter types.
- for (ObjCMethodDecl::param_iterator P = D->param_begin(),
+ for (ObjCMethodDecl::param_iterator P = D->param_begin(),
PEnd = D->param_end(), FoundP = FoundMethod->param_begin();
P != PEnd; ++P, ++FoundP) {
- if (!Importer.IsStructurallyEquivalent((*P)->getType(),
+ if (!Importer.IsStructurallyEquivalent((*P)->getType(),
(*FoundP)->getType())) {
- Importer.FromDiag((*P)->getLocation(),
+ Importer.FromDiag((*P)->getLocation(),
diag::err_odr_objc_method_param_type_inconsistent)
<< D->isInstanceMethod() << Name
<< (*P)->getType() << (*FoundP)->getType();
// Import the parameters
SmallVector<ParmVarDecl *, 5> ToParams;
- for (auto *FromP : D->params()) {
+ for (auto *FromP : D->parameters()) {
ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP));
if (!ToP)
return nullptr;
return ToMethod;
}
+Decl *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 (ToD)
+ return ToD;
+
+ TypeSourceInfo *BoundInfo = Importer.Import(D->getTypeSourceInfo());
+ if (!BoundInfo)
+ return nullptr;
+
+ ObjCTypeParamDecl *Result = ObjCTypeParamDecl::Create(
+ Importer.getToContext(), DC,
+ D->getVariance(),
+ Importer.Import(D->getVarianceLoc()),
+ D->getIndex(),
+ Importer.Import(D->getLocation()),
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getColonLoc()),
+ BoundInfo);
+ Importer.Imported(D, Result);
+ Result->setLexicalDeclContext(LexicalDC);
+ return Result;
+}
+
Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
// Import the major distinguishing characteristics of a category.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
ObjCInterfaceDecl *ToInterface
= cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface()));
Importer.Import(D->getCategoryNameLoc()),
Name.getAsIdentifierInfo(),
ToInterface,
+ /*TypeParamList=*/nullptr,
Importer.Import(D->getIvarLBraceLoc()),
Importer.Import(D->getIvarRBraceLoc()));
ToCategory->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToCategory);
Importer.Imported(D, ToCategory);
+ // Import the type parameter list after calling Imported, to avoid
+ // loops when bringing in their DeclContext.
+ ToCategory->setTypeParamList(ImportObjCTypeParamList(
+ D->getTypeParamList()));
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
ObjCProtocolDecl *MergeWithProtocol = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
continue;
return ToProto;
}
+Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+
+ SourceLocation ExternLoc = Importer.Import(D->getExternLoc());
+ SourceLocation LangLoc = Importer.Import(D->getLocation());
+
+ bool HasBraces = D->hasBraces();
+
+ LinkageSpecDecl *ToLinkageSpec =
+ LinkageSpecDecl::Create(Importer.getToContext(),
+ DC,
+ ExternLoc,
+ LangLoc,
+ D->getLanguage(),
+ HasBraces);
+
+ if (HasBraces) {
+ SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc());
+ ToLinkageSpec->setRBraceLoc(RBraceLoc);
+ }
+
+ ToLinkageSpec->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToLinkageSpec);
+
+ Importer.Imported(D, ToLinkageSpec);
+
+ return ToLinkageSpec;
+}
+
bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
ObjCInterfaceDecl *To,
ImportDefinitionKind Kind) {
// If this class has a superclass, import it.
if (From->getSuperClass()) {
- ObjCInterfaceDecl *Super = cast_or_null<ObjCInterfaceDecl>(
- Importer.Import(From->getSuperClass()));
- if (!Super)
+ TypeSourceInfo *SuperTInfo = Importer.Import(From->getSuperClassTInfo());
+ if (!SuperTInfo)
return true;
-
- To->setSuperClass(Super);
- To->setSuperClassLoc(Importer.Import(From->getSuperClassLoc()));
+
+ To->setSuperClass(SuperTInfo);
}
// Import protocols
return false;
}
+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);
+ }
+
+ return ObjCTypeParamList::create(Importer.getToContext(),
+ Importer.Import(list->getLAngleLoc()),
+ toTypeParams,
+ Importer.Import(list->getRAngleLoc()));
+}
+
Decl *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
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Look for an existing interface with the same name.
ObjCInterfaceDecl *MergeWithIface = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
if (!ToIface) {
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getAtStartLoc()),
- Name.getAsIdentifierInfo(),
+ Name.getAsIdentifierInfo(),
+ /*TypeParamList=*/nullptr,
/*PrevDecl=*/nullptr, Loc,
D->isImplicitInterfaceDecl());
ToIface->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToIface);
}
Importer.Imported(D, ToIface);
+ // Import the type parameter list after calling Imported, to avoid
+ // loops when bringing in their DeclContext.
+ ToIface->setTypeParamList(ImportObjCTypeParamList(
+ D->getTypeParamListAsWritten()));
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface))
return nullptr;
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Check whether we have already imported this property.
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (ObjCPropertyDecl *FoundProp
= dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) {
// Check property types.
- if (!Importer.IsStructurallyEquivalent(D->getType(),
+ if (!Importer.IsStructurallyEquivalent(D->getType(),
FoundProp->getType())) {
Importer.ToDiag(Loc, diag::err_odr_objc_property_type_inconsistent)
<< Name << D->getType() << FoundProp->getType();
}
// Import the type.
- TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo());
- if (!T)
+ TypeSourceInfo *TSI = Importer.Import(D->getTypeSourceInfo());
+ if (!TSI)
return nullptr;
// Create the new property.
Name.getAsIdentifierInfo(),
Importer.Import(D->getAtLoc()),
Importer.Import(D->getLParenLoc()),
- T,
+ Importer.Import(D->getType()),
+ TSI,
D->getPropertyImplementation());
Importer.Imported(D, ToProperty);
ToProperty->setLexicalDeclContext(LexicalDC);
ToProperty->setPropertyAttributes(D->getPropertyAttributes());
ToProperty->setPropertyAttributesAsWritten(
D->getPropertyAttributesAsWritten());
- ToProperty->setGetterName(Importer.Import(D->getGetterName()));
- ToProperty->setSetterName(Importer.Import(D->getSetterName()));
+ 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(
}
ObjCPropertyImplDecl *ToImpl
- = InImpl->FindPropertyImplDecl(Property->getIdentifier());
+ = InImpl->FindPropertyImplDecl(Property->getIdentifier(),
+ Property->getQueryKind());
if (!ToImpl) {
ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getLocStart()),
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// We may already have a template of the same name; try to find and match it.
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
CXXRecordDecl *DTemplated = D->getTemplatedDecl();
// Create the declaration that is being templated.
- SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart());
- SourceLocation IdLoc = Importer.Import(DTemplated->getLocation());
- CXXRecordDecl *D2Templated = CXXRecordDecl::Create(Importer.getToContext(),
- DTemplated->getTagKind(),
- DC, StartLoc, IdLoc,
- Name.getAsIdentifierInfo());
- D2Templated->setAccess(DTemplated->getAccess());
- D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
- D2Templated->setLexicalDeclContext(LexicalDC);
-
+ // Create the declaration that is being templated.
+ CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>(
+ Importer.Import(DTemplated));
+ if (!D2Templated)
+ return nullptr;
+
+ // Resolve possible cyclic import.
+ if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D))
+ return AlreadyImported;
+
// Create the class template declaration itself.
TemplateParameterList *TemplateParams
= ImportTemplateParameterList(D->getTemplateParameters());
ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC,
Loc, Name, TemplateParams,
- D2Templated,
- /*PrevDecl=*/nullptr);
+ D2Templated);
D2Templated->setDescribedClassTemplate(D2);
D2->setAccess(D->getAccess());
return Importer.Imported(D, ImportedDef);
}
- ClassTemplateDecl *ClassTemplate
- = cast_or_null<ClassTemplateDecl>(Importer.Import(
- D->getSpecializedTemplate()));
- if (!ClassTemplate)
+ ClassTemplateDecl *ClassTemplate
+ = cast_or_null<ClassTemplateDecl>(Importer.Import(
+ D->getSpecializedTemplate()));
+ if (!ClassTemplate)
+ return nullptr;
+
+ // 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());
+
+ // Import template arguments.
+ SmallVector<TemplateArgument, 2> TemplateArgs;
+ if (ImportTemplateArguments(D->getTemplateArgs().data(),
+ D->getTemplateArgs().size(),
+ TemplateArgs))
+ return nullptr;
+
+ // 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.
+
+ // FIXME: Check for specialization vs. instantiation errors.
+
+ 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.Imported(D, FoundDef);
+ }
+ }
+ } else {
+ // Create a new specialization.
+ if (ClassTemplatePartialSpecializationDecl *PartialSpec =
+ dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
+
+ // Import TemplateArgumentListInfo
+ TemplateArgumentListInfo ToTAInfo;
+ auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
+ for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) {
+ bool Error = false;
+ auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I], Error);
+ if (Error)
+ return nullptr;
+ ToTAInfo.addArgument(ToLoc);
+ }
+
+ QualType CanonInjType = Importer.Import(
+ PartialSpec->getInjectedSpecializationType());
+ if (CanonInjType.isNull())
+ return nullptr;
+ CanonInjType = CanonInjType.getCanonicalType();
+
+ TemplateParameterList *ToTPList = ImportTemplateParameterList(
+ PartialSpec->getTemplateParameters());
+ if (!ToTPList && PartialSpec->getTemplateParameters())
+ return nullptr;
+
+ D2 = ClassTemplatePartialSpecializationDecl::Create(
+ Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc,
+ ToTPList, ClassTemplate,
+ llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()),
+ ToTAInfo, CanonInjType, nullptr);
+
+ } else {
+ D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(),
+ D->getTagKind(), DC,
+ StartLoc, IdLoc,
+ ClassTemplate,
+ TemplateArgs,
+ /*PrevDecl=*/nullptr);
+ }
+
+ 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()));
+
+ Importer.Imported(D, D2);
+
+ 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()));
+ }
+
+ SourceLocation POI = Importer.Import(D->getPointOfInstantiation());
+ if (POI.isValid())
+ D2->setPointOfInstantiation(POI);
+ else if (D->getPointOfInstantiation().isValid())
+ return nullptr;
+
+ D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind());
+
+ // Add the specialization to this context.
+ D2->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(D2);
+ }
+ Importer.Imported(D, D2);
+ if (D->isCompleteDefinition() && ImportDefinition(D, D2))
+ return nullptr;
+
+ return D2;
+}
+
+Decl *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
+ // definition and map to that.
+ VarDecl *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.Imported(D, ImportedDef);
+ }
+
+ // Import the major distinguishing characteristics of this variable template.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return nullptr;
+ if (ToD)
+ return ToD;
+
+ // We may already have a template of the same name; try to find and match it.
+ assert(!DC->isFunctionOrMethod() &&
+ "Variable templates cannot be declared at function scope");
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
+ SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ continue;
+
+ Decl *Found = FoundDecls[I];
+ if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
+ if (IsStructuralMatch(D, FoundTemplate)) {
+ // The variable templates structurally match; call it the same template.
+ Importer.Imported(D->getTemplatedDecl(),
+ FoundTemplate->getTemplatedDecl());
+ return Importer.Imported(D, FoundTemplate);
+ }
+ }
+
+ ConflictingDecls.push_back(FoundDecls[I]);
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ }
+
+ if (!Name)
+ return nullptr;
+
+ VarDecl *DTemplated = D->getTemplatedDecl();
+
+ // Import the type.
+ QualType T = Importer.Import(DTemplated->getType());
+ if (T.isNull())
+ return nullptr;
+
+ // Create the declaration that is being templated.
+ SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart());
+ SourceLocation IdLoc = Importer.Import(DTemplated->getLocation());
+ TypeSourceInfo *TInfo = Importer.Import(DTemplated->getTypeSourceInfo());
+ VarDecl *D2Templated = VarDecl::Create(Importer.getToContext(), DC, StartLoc,
+ IdLoc, Name.getAsIdentifierInfo(), T,
+ TInfo, DTemplated->getStorageClass());
+ D2Templated->setAccess(DTemplated->getAccess());
+ D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
+ D2Templated->setLexicalDeclContext(LexicalDC);
+
+ // Importer.Imported(DTemplated, D2Templated);
+ // LexicalDC->addDeclInternal(D2Templated);
+
+ // Merge the initializer.
+ if (ImportDefinition(DTemplated, D2Templated))
+ return nullptr;
+
+ // Create the variable template declaration itself.
+ TemplateParameterList *TemplateParams =
+ ImportTemplateParameterList(D->getTemplateParameters());
+ if (!TemplateParams)
+ return nullptr;
+
+ VarTemplateDecl *D2 = VarTemplateDecl::Create(
+ Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated);
+ D2Templated->setDescribedVarTemplate(D2);
+
+ D2->setAccess(D->getAccess());
+ D2->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(D2);
+
+ // Note the relationship between the variable templates.
+ Importer.Imported(D, D2);
+ Importer.Imported(DTemplated, D2Templated);
+
+ if (DTemplated->isThisDeclarationADefinition() &&
+ !D2Templated->isThisDeclarationADefinition()) {
+ // FIXME: Import definition!
+ }
+
+ return D2;
+}
+
+Decl *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.Imported(D, ImportedDef);
+ }
+
+ VarTemplateDecl *VarTemplate = cast_or_null<VarTemplateDecl>(
+ Importer.Import(D->getSpecializedTemplate()));
+ if (!VarTemplate)
+ return nullptr;
+
+ // 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;
+ }
+
+ // Import the location of this declaration.
+ SourceLocation StartLoc = Importer.Import(D->getLocStart());
+ SourceLocation IdLoc = Importer.Import(D->getLocation());
+
+ // Import template arguments.
+ SmallVector<TemplateArgument, 2> TemplateArgs;
+ if (ImportTemplateArguments(D->getTemplateArgs().data(),
+ D->getTemplateArgs().size(), TemplateArgs))
+ return nullptr;
+
+ // Try to find an existing specialization with these template arguments.
+ void *InsertPos = nullptr;
+ VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization(
+ TemplateArgs, InsertPos);
+ if (D2) {
+ // We already have a variable template specialization with these template
+ // arguments.
+
+ // FIXME: Check for specialization vs. instantiation errors.
+
+ if (VarDecl *FoundDef = D2->getDefinition()) {
+ if (!D->isThisDeclarationADefinition() ||
+ IsStructuralMatch(D, FoundDef)) {
+ // The record types structurally match, or the "from" translation
+ // unit only had a forward declaration anyway; call it the same
+ // variable.
+ return Importer.Imported(D, FoundDef);
+ }
+ }
+ } else {
+
+ // Import the type.
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return nullptr;
+ TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+
+ // Create a new specialization.
+ D2 = VarTemplateSpecializationDecl::Create(
+ Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo,
+ D->getStorageClass(), TemplateArgs);
+ D2->setSpecializationKind(D->getSpecializationKind());
+ D2->setTemplateArgsInfo(D->getTemplateArgsInfo());
+
+ // Add this specialization to the class template.
+ VarTemplate->AddSpecialization(D2, InsertPos);
+
+ // Import the qualifier, if any.
+ D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+
+ // Add the specialization to this context.
+ D2->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(D2);
+ }
+ Importer.Imported(D, D2);
+
+ if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2))
+ return nullptr;
+
+ return D2;
+}
+
+//----------------------------------------------------------------------------
+// Import Statements
+//----------------------------------------------------------------------------
+
+DeclGroupRef ASTNodeImporter::ImportDeclGroup(DeclGroupRef DG) {
+ if (DG.isNull())
+ return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0);
+ size_t NumDecls = DG.end() - DG.begin();
+ SmallVector<Decl *, 1> ToDecls(NumDecls);
+ auto &_Importer = this->Importer;
+ std::transform(DG.begin(), DG.end(), ToDecls.begin(),
+ [&_Importer](Decl *D) -> Decl * {
+ return _Importer.Import(D);
+ });
+ return DeclGroupRef::Create(Importer.getToContext(),
+ ToDecls.begin(),
+ NumDecls);
+}
+
+ Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
+ Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
+ << S->getStmtClassName();
+ return nullptr;
+ }
+
+
+Stmt *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++) {
+ StringLiteral *Clobber = cast_or_null<StringLiteral>(
+ Importer.Import(S->getClobberStringLiteral(I)));
+ if (!Clobber)
+ return nullptr;
+ Clobbers.push_back(Clobber);
+ }
+
+ SmallVector<StringLiteral *, 4> Constraints;
+ for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
+ StringLiteral *Output = cast_or_null<StringLiteral>(
+ Importer.Import(S->getOutputConstraintLiteral(I)));
+ if (!Output)
+ return nullptr;
+ Constraints.push_back(Output);
+ }
+
+ for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
+ StringLiteral *Input = cast_or_null<StringLiteral>(
+ Importer.Import(S->getInputConstraintLiteral(I)));
+ if (!Input)
+ return nullptr;
+ Constraints.push_back(Input);
+ }
+
+ SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs());
+ if (ImportContainerChecked(S->outputs(), Exprs))
+ return nullptr;
+
+ if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs()))
+ return nullptr;
+
+ StringLiteral *AsmStr = cast_or_null<StringLiteral>(
+ Importer.Import(S->getAsmString()));
+ if (!AsmStr)
+ return nullptr;
+
+ return new (Importer.getToContext()) GCCAsmStmt(
+ Importer.getToContext(),
+ Importer.Import(S->getAsmLoc()),
+ S->isSimple(),
+ S->isVolatile(),
+ S->getNumOutputs(),
+ S->getNumInputs(),
+ Names.data(),
+ Constraints.data(),
+ Exprs.data(),
+ AsmStr,
+ S->getNumClobbers(),
+ Clobbers.data(),
+ Importer.Import(S->getRParenLoc()));
+}
+
+Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {
+ DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup());
+ for (Decl *ToD : ToDG) {
+ if (!ToD)
+ return nullptr;
+ }
+ SourceLocation ToStartLoc = Importer.Import(S->getStartLoc());
+ SourceLocation ToEndLoc = Importer.Import(S->getEndLoc());
+ return new (Importer.getToContext()) DeclStmt(ToDG, ToStartLoc, ToEndLoc);
+}
+
+Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
+ SourceLocation ToSemiLoc = Importer.Import(S->getSemiLoc());
+ return new (Importer.getToContext()) NullStmt(ToSemiLoc,
+ S->hasLeadingEmptyMacro());
+}
+
+Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
+ llvm::SmallVector<Stmt *, 8> ToStmts(S->size());
+
+ if (ImportContainerChecked(S->body(), ToStmts))
+ return nullptr;
+
+ SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
+ SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc());
+ return new (Importer.getToContext()) CompoundStmt(Importer.getToContext(),
+ ToStmts,
+ ToLBraceLoc, ToRBraceLoc);
+}
+
+Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
+ Expr *ToLHS = Importer.Import(S->getLHS());
+ if (!ToLHS)
+ return nullptr;
+ Expr *ToRHS = Importer.Import(S->getRHS());
+ if (!ToRHS && S->getRHS())
+ return nullptr;
+ SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc());
+ SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc());
+ SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
+ return new (Importer.getToContext()) CaseStmt(ToLHS, ToRHS,
+ ToCaseLoc, ToEllipsisLoc,
+ ToColonLoc);
+}
+
+Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {
+ SourceLocation ToDefaultLoc = Importer.Import(S->getDefaultLoc());
+ SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) DefaultStmt(ToDefaultLoc, ToColonLoc,
+ ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitLabelStmt(LabelStmt *S) {
+ SourceLocation ToIdentLoc = Importer.Import(S->getIdentLoc());
+ LabelDecl *ToLabelDecl =
+ cast_or_null<LabelDecl>(Importer.Import(S->getDecl()));
+ if (!ToLabelDecl && S->getDecl())
+ return nullptr;
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) LabelStmt(ToIdentLoc, ToLabelDecl,
+ ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) {
+ SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc());
+ ArrayRef<const Attr*> FromAttrs(S->getAttrs());
+ SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size());
+ ASTContext &_ToContext = Importer.getToContext();
+ std::transform(FromAttrs.begin(), FromAttrs.end(), ToAttrs.begin(),
+ [&_ToContext](const Attr *A) -> const Attr * {
+ return A->clone(_ToContext);
+ });
+ for (const Attr *ToA : ToAttrs) {
+ if (!ToA)
+ return nullptr;
+ }
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return AttributedStmt::Create(Importer.getToContext(), ToAttrLoc,
+ ToAttrs, ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitIfStmt(IfStmt *S) {
+ SourceLocation ToIfLoc = Importer.Import(S->getIfLoc());
+ 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);
+}
+
+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;
+ SwitchStmt *ToStmt = new (Importer.getToContext()) SwitchStmt(
+ Importer.getToContext(), ToInit,
+ ToConditionVariable, ToCondition);
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ ToStmt->setBody(ToBody);
+ ToStmt->setSwitchLoc(Importer.Import(S->getSwitchLoc()));
+ // Now we have to re-chain the cases.
+ SwitchCase *LastChainedSwitchCase = nullptr;
+ for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr;
+ SC = SC->getNextSwitchCase()) {
+ SwitchCase *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC));
+ if (!ToSC)
+ return nullptr;
+ if (LastChainedSwitchCase)
+ LastChainedSwitchCase->setNextSwitchCase(ToSC);
+ else
+ ToStmt->setSwitchCaseList(ToSC);
+ LastChainedSwitchCase = ToSC;
+ }
+ return ToStmt;
+}
+
+Stmt *ASTNodeImporter::VisitWhileStmt(WhileStmt *S) {
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc());
+ return new (Importer.getToContext()) WhileStmt(Importer.getToContext(),
+ ToConditionVariable,
+ ToCondition, ToBody,
+ ToWhileLoc);
+}
+
+Stmt *ASTNodeImporter::VisitDoStmt(DoStmt *S) {
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ SourceLocation ToDoLoc = Importer.Import(S->getDoLoc());
+ SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) DoStmt(ToBody, ToCondition,
+ ToDoLoc, ToWhileLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitForStmt(ForStmt *S) {
+ Stmt *ToInit = Importer.Import(S->getInit());
+ if (!ToInit && S->getInit())
+ return nullptr;
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToInc = Importer.Import(S->getInc());
+ if (!ToInc && S->getInc())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToLParenLoc = Importer.Import(S->getLParenLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) ForStmt(Importer.getToContext(),
+ ToInit, ToCondition,
+ ToConditionVariable,
+ ToInc, ToBody,
+ ToForLoc, ToLParenLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitGotoStmt(GotoStmt *S) {
+ LabelDecl *ToLabel = nullptr;
+ if (LabelDecl *FromLabel = S->getLabel()) {
+ ToLabel = dyn_cast_or_null<LabelDecl>(Importer.Import(FromLabel));
+ if (!ToLabel)
+ return nullptr;
+ }
+ SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc());
+ SourceLocation ToLabelLoc = Importer.Import(S->getLabelLoc());
+ return new (Importer.getToContext()) GotoStmt(ToLabel,
+ ToGotoLoc, ToLabelLoc);
+}
+
+Stmt *ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+ SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc());
+ SourceLocation ToStarLoc = Importer.Import(S->getStarLoc());
+ Expr *ToTarget = Importer.Import(S->getTarget());
+ if (!ToTarget && S->getTarget())
+ return nullptr;
+ return new (Importer.getToContext()) IndirectGotoStmt(ToGotoLoc, ToStarLoc,
+ ToTarget);
+}
+
+Stmt *ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) {
+ SourceLocation ToContinueLoc = Importer.Import(S->getContinueLoc());
+ return new (Importer.getToContext()) ContinueStmt(ToContinueLoc);
+}
+
+Stmt *ASTNodeImporter::VisitBreakStmt(BreakStmt *S) {
+ SourceLocation ToBreakLoc = Importer.Import(S->getBreakLoc());
+ return new (Importer.getToContext()) BreakStmt(ToBreakLoc);
+}
+
+Stmt *ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) {
+ SourceLocation ToRetLoc = Importer.Import(S->getReturnLoc());
+ Expr *ToRetExpr = Importer.Import(S->getRetValue());
+ if (!ToRetExpr && S->getRetValue())
+ return nullptr;
+ VarDecl *NRVOCandidate = const_cast<VarDecl*>(S->getNRVOCandidate());
+ VarDecl *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate));
+ if (!ToNRVOCandidate && NRVOCandidate)
+ return nullptr;
+ return new (Importer.getToContext()) ReturnStmt(ToRetLoc, ToRetExpr,
+ ToNRVOCandidate);
+}
+
+Stmt *ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ SourceLocation ToCatchLoc = Importer.Import(S->getCatchLoc());
+ VarDecl *ToExceptionDecl = nullptr;
+ if (VarDecl *FromExceptionDecl = S->getExceptionDecl()) {
+ ToExceptionDecl =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl));
+ if (!ToExceptionDecl)
+ return nullptr;
+ }
+ Stmt *ToHandlerBlock = Importer.Import(S->getHandlerBlock());
+ if (!ToHandlerBlock && S->getHandlerBlock())
+ return nullptr;
+ return new (Importer.getToContext()) CXXCatchStmt(ToCatchLoc,
+ ToExceptionDecl,
+ ToHandlerBlock);
+}
+
+Stmt *ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) {
+ SourceLocation ToTryLoc = Importer.Import(S->getTryLoc());
+ Stmt *ToTryBlock = Importer.Import(S->getTryBlock());
+ if (!ToTryBlock && S->getTryBlock())
+ return nullptr;
+ SmallVector<Stmt *, 1> ToHandlers(S->getNumHandlers());
+ for (unsigned HI = 0, HE = S->getNumHandlers(); HI != HE; ++HI) {
+ CXXCatchStmt *FromHandler = S->getHandler(HI);
+ if (Stmt *ToHandler = Importer.Import(FromHandler))
+ ToHandlers[HI] = ToHandler;
+ else
+ return nullptr;
+ }
+ return CXXTryStmt::Create(Importer.getToContext(), ToTryLoc, ToTryBlock,
+ ToHandlers);
+}
+
+Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
+ DeclStmt *ToRange =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt()));
+ if (!ToRange && S->getRangeStmt())
+ return nullptr;
+ DeclStmt *ToBegin =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginStmt()));
+ if (!ToBegin && S->getBeginStmt())
+ return nullptr;
+ DeclStmt *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;
+ DeclStmt *ToLoopVar =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getLoopVarStmt()));
+ if (!ToLoopVar && S->getLoopVarStmt())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation 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);
+}
+
+Stmt *ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+ Stmt *ToElem = Importer.Import(S->getElement());
+ if (!ToElem && S->getElement())
+ return nullptr;
+ Expr *ToCollect = Importer.Import(S->getCollection());
+ if (!ToCollect && S->getCollection())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) ObjCForCollectionStmt(ToElem,
+ ToCollect,
+ ToBody, ToForLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+ SourceLocation ToAtCatchLoc = Importer.Import(S->getAtCatchLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ VarDecl *ToExceptionDecl = nullptr;
+ if (VarDecl *FromExceptionDecl = S->getCatchParamDecl()) {
+ ToExceptionDecl =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl));
+ if (!ToExceptionDecl)
+ return nullptr;
+ }
+ Stmt *ToBody = Importer.Import(S->getCatchBody());
+ if (!ToBody && S->getCatchBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtCatchStmt(ToAtCatchLoc,
+ ToRParenLoc,
+ ToExceptionDecl,
+ ToBody);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+ SourceLocation ToAtFinallyLoc = Importer.Import(S->getAtFinallyLoc());
+ Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyBody());
+ if (!ToAtFinallyStmt && S->getFinallyBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtFinallyStmt(ToAtFinallyLoc,
+ ToAtFinallyStmt);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+ SourceLocation ToAtTryLoc = Importer.Import(S->getAtTryLoc());
+ Stmt *ToAtTryStmt = Importer.Import(S->getTryBody());
+ if (!ToAtTryStmt && S->getTryBody())
+ return nullptr;
+ SmallVector<Stmt *, 1> ToCatchStmts(S->getNumCatchStmts());
+ for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) {
+ ObjCAtCatchStmt *FromCatchStmt = S->getCatchStmt(CI);
+ if (Stmt *ToCatchStmt = Importer.Import(FromCatchStmt))
+ ToCatchStmts[CI] = ToCatchStmt;
+ else
+ return nullptr;
+ }
+ Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyStmt());
+ if (!ToAtFinallyStmt && S->getFinallyStmt())
+ return nullptr;
+ return ObjCAtTryStmt::Create(Importer.getToContext(),
+ ToAtTryLoc, ToAtTryStmt,
+ ToCatchStmts.begin(), ToCatchStmts.size(),
+ ToAtFinallyStmt);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtSynchronizedStmt
+ (ObjCAtSynchronizedStmt *S) {
+ SourceLocation ToAtSynchronizedLoc =
+ Importer.Import(S->getAtSynchronizedLoc());
+ Expr *ToSynchExpr = Importer.Import(S->getSynchExpr());
+ if (!ToSynchExpr && S->getSynchExpr())
+ return nullptr;
+ Stmt *ToSynchBody = Importer.Import(S->getSynchBody());
+ if (!ToSynchBody && S->getSynchBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtSynchronizedStmt(
+ ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+ SourceLocation ToAtThrowLoc = Importer.Import(S->getThrowLoc());
+ Expr *ToThrow = Importer.Import(S->getThrowExpr());
+ if (!ToThrow && S->getThrowExpr())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtThrowStmt(ToAtThrowLoc, ToThrow);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAutoreleasePoolStmt
+ (ObjCAutoreleasePoolStmt *S) {
+ SourceLocation ToAtLoc = Importer.Import(S->getAtLoc());
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(ToAtLoc,
+ ToSubStmt);
+}
+
+//----------------------------------------------------------------------------
+// Import Expressions
+//----------------------------------------------------------------------------
+Expr *ASTNodeImporter::VisitExpr(Expr *E) {
+ Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node)
+ << E->getStmtClassName();
+ return nullptr;
+}
+
+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;
+
+ TypeSourceInfo *TInfo = Importer.Import(E->getWrittenTypeInfo());
+ if (!TInfo)
+ return nullptr;
+
+ return new (Importer.getToContext()) VAArgExpr(
+ Importer.Import(E->getBuiltinLoc()), SubExpr, TInfo,
+ Importer.Import(E->getRParenLoc()), T, 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()));
+}
+
+Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ StringLiteral *SL = cast_or_null<StringLiteral>(
+ Importer.Import(E->getFunctionName()));
+ if (!SL && E->getFunctionName())
+ return nullptr;
+
+ return new (Importer.getToContext()) PredefinedExpr(
+ Importer.Import(E->getLocStart()), T, E->getIdentType(), SL);
+}
+
+Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
+ ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl()));
+ if (!ToD)
+ return nullptr;
+
+ NamedDecl *FoundD = nullptr;
+ if (E->getDecl() != E->getFoundDecl()) {
+ FoundD = cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl()));
+ if (!FoundD)
+ return nullptr;
+ }
+
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+
+ TemplateArgumentListInfo ToTAInfo;
+ TemplateArgumentListInfo *ResInfo = nullptr;
+ if (E->hasExplicitTemplateArgs()) {
+ for (const auto &FromLoc : E->template_arguments()) {
+ bool Error = false;
+ TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error);
+ if (Error)
+ return nullptr;
+ ToTAInfo.addArgument(ToTALoc);
+ }
+ ResInfo = &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);
+ 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);
+}
+
+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()));
+
+ assert(D.isArrayRangeDesignator());
+ return Designator(D.getFirstExprIndex(),
+ Importer.Import(D.getLBracketLoc()),
+ Importer.Import(D.getEllipsisLoc()),
+ Importer.Import(D.getRBracketLoc()));
+}
+
+
+Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) {
+ Expr *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit()));
+ if (!Init)
+ return nullptr;
+
+ SmallVector<Expr *, 4> IndexExprs(DIE->getNumSubExprs() - 1);
+ // List elements from the second, the first is Init itself
+ for (unsigned I = 1, E = DIE->getNumSubExprs(); I < E; I++) {
+ if (Expr *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I))))
+ IndexExprs[I - 1] = Arg;
+ else
+ return nullptr;
+ }
+
+ SmallVector<Designator, 4> Designators(DIE->size());
+ llvm::transform(DIE->designators(), Designators.begin(),
+ [this](const Designator &D) -> Designator {
+ return ImportDesignator(D);
+ });
+
+ for (const Designator &D : DIE->designators())
+ if (D.isFieldDesignator() && !D.getFieldName())
+ return nullptr;
+
+ return DesignatedInitExpr::Create(
+ Importer.getToContext(), Designators,
+ IndexExprs, Importer.Import(DIE->getEqualOrColonLoc()),
+ DIE->usesGNUSyntax(), Init);
+}
+
+Expr *ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ return new (Importer.getToContext())
+ CXXNullPtrLiteralExpr(T, Importer.Import(E->getLocation()));
+}
+
+Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ return IntegerLiteral::Create(Importer.getToContext(),
+ E->getValue(), T,
+ Importer.Import(E->getLocation()));
+}
+
+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()));
+}
+
+Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ return new (Importer.getToContext()) CharacterLiteral(E->getValue(),
+ E->getKind(), T,
+ Importer.Import(E->getLocation()));
+}
+
+Expr *ASTNodeImporter::VisitStringLiteral(StringLiteral *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ SmallVector<SourceLocation, 4> Locations(E->getNumConcatenated());
+ ImportArray(E->tokloc_begin(), E->tokloc_end(), Locations.begin());
+
+ return StringLiteral::Create(Importer.getToContext(), E->getBytes(),
+ E->getKind(), E->isPascal(), T,
+ Locations.data(), Locations.size());
+}
+
+Expr *ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ TypeSourceInfo *TInfo = Importer.Import(E->getTypeSourceInfo());
+ if (!TInfo)
+ return nullptr;
+
+ Expr *Init = Importer.Import(E->getInitializer());
+ if (!Init)
+ return nullptr;
+
+ return new (Importer.getToContext()) CompoundLiteralExpr(
+ Importer.Import(E->getLParenLoc()), TInfo, T, E->getValueKind(),
+ Init, E->isFileScope());
+}
+
+Expr *ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ SmallVector<Expr *, 6> Exprs(E->getNumSubExprs());
+ if (ImportArrayChecked(
+ E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(),
+ Exprs.begin()))
+ return nullptr;
+
+ return new (Importer.getToContext()) AtomicExpr(
+ Importer.Import(E->getBuiltinLoc()), Exprs, T, E->getOp(),
+ Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ LabelDecl *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel()));
+ if (!ToLabel)
+ return nullptr;
+
+ return new (Importer.getToContext()) AddrLabelExpr(
+ Importer.Import(E->getAmpAmpLoc()), Importer.Import(E->getLabelLoc()),
+ ToLabel, T);
+}
+
+Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
+ return nullptr;
+
+ return new (Importer.getToContext())
+ ParenExpr(Importer.Import(E->getLParen()),
+ Importer.Import(E->getRParen()),
+ SubExpr);
+}
+
+Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
+ SmallVector<Expr *, 4> Exprs(E->getNumExprs());
+ if (ImportContainerChecked(E->exprs(), Exprs))
+ return nullptr;
+
+ return new (Importer.getToContext()) ParenListExpr(
+ Importer.getToContext(), Importer.Import(E->getLParenLoc()),
+ Exprs, Importer.Import(E->getLParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ CompoundStmt *ToSubStmt = cast_or_null<CompoundStmt>(
+ Importer.Import(E->getSubStmt()));
+ if (!ToSubStmt && E->getSubStmt())
+ return nullptr;
+
+ return new (Importer.getToContext()) StmtExpr(ToSubStmt, T,
+ Importer.Import(E->getLParenLoc()), Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
+ return nullptr;
+
+ return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(),
+ T, E->getValueKind(),
+ E->getObjectKind(),
+ Importer.Import(E->getOperatorLoc()));
+}
+
+Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTraitExpr *E) {
+ QualType ResultType = Importer.Import(E->getType());
+
+ if (E->isArgumentType()) {
+ TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo());
+ if (!TInfo)
+ return nullptr;
+
+ return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
+ TInfo, ResultType,
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getRParenLoc()));
+ }
+
+ Expr *SubExpr = Importer.Import(E->getArgumentExpr());
+ if (!SubExpr)
+ return nullptr;
+
+ return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
+ SubExpr, ResultType,
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *LHS = Importer.Import(E->getLHS());
+ if (!LHS)
+ return nullptr;
+
+ Expr *RHS = Importer.Import(E->getRHS());
+ if (!RHS)
+ return nullptr;
+
+ return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(),
+ T, E->getValueKind(),
+ E->getObjectKind(),
+ Importer.Import(E->getOperatorLoc()),
+ 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;
+
+ Expr *ToCond = Importer.Import(E->getCond());
+ if (!ToCond)
+ return nullptr;
+
+ return new (Importer.getToContext()) ConditionalOperator(
+ ToCond, Importer.Import(E->getQuestionLoc()),
+ ToLHS, Importer.Import(E->getColonLoc()),
+ ToRHS, T, E->getValueKind(), E->getObjectKind());
+}
+
+Expr *ASTNodeImporter::VisitBinaryConditionalOperator(
+ BinaryConditionalOperator *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *Common = Importer.Import(E->getCommon());
+ if (!Common)
+ return nullptr;
+
+ Expr *Cond = Importer.Import(E->getCond());
+ if (!Cond)
+ return nullptr;
+
+ OpaqueValueExpr *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;
+
+ return new (Importer.getToContext()) BinaryConditionalOperator(
+ Common, OpaqueValue, Cond, TrueExpr, FalseExpr,
+ Importer.Import(E->getQuestionLoc()), Importer.Import(E->getColonLoc()),
+ T, E->getValueKind(), E->getObjectKind());
+}
+
+Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo());
+ if (!ToQueried)
+ return nullptr;
+
+ Expr *Dim = Importer.Import(E->getDimensionExpression());
+ if (!Dim && E->getDimensionExpression())
+ return nullptr;
+
+ return new (Importer.getToContext()) ArrayTypeTraitExpr(
+ Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
+ E->getValue(), Dim, Importer.Import(E->getLocEnd()), T);
+}
+
+Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToQueried = Importer.Import(E->getQueriedExpression());
+ if (!ToQueried)
+ return nullptr;
+
+ return new (Importer.getToContext()) ExpressionTraitExpr(
+ Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
+ E->getValue(), Importer.Import(E->getLocEnd()), T);
+}
+
+Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *SourceExpr = Importer.Import(E->getSourceExpr());
+ if (!SourceExpr && E->getSourceExpr())
+ return nullptr;
+
+ return new (Importer.getToContext()) OpaqueValueExpr(
+ Importer.Import(E->getLocation()), T, E->getValueKind(),
+ E->getObjectKind(), SourceExpr);
+}
+
+Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToLHS = Importer.Import(E->getLHS());
+ if (!ToLHS)
+ return nullptr;
+
+ Expr *ToRHS = Importer.Import(E->getRHS());
+ if (!ToRHS)
+ return nullptr;
+
+ return new (Importer.getToContext()) ArraySubscriptExpr(
+ ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(),
+ Importer.Import(E->getRBracketLoc()));
+}
+
+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;
+
+ Expr *LHS = Importer.Import(E->getLHS());
+ if (!LHS)
+ return nullptr;
+
+ 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());
+}
+
+bool 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);
+ else
+ return true;
+ }
+ return false;
+}
+
+Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
return nullptr;
- // Import the context of this declaration.
- DeclContext *DC = ClassTemplate->getDeclContext();
- if (!DC)
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
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());
+ return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+ SubExpr, &BasePath, E->getValueKind());
+}
- // Import template arguments.
- SmallVector<TemplateArgument, 2> TemplateArgs;
- if (ImportTemplateArguments(D->getTemplateArgs().data(),
- D->getTemplateArgs().size(),
- TemplateArgs))
+Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
return nullptr;
- // 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.
-
- // FIXME: Check for specialization vs. instantiation errors.
-
- 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.Imported(D, FoundDef);
- }
- }
- } else {
- // Create a new specialization.
- D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(),
- D->getTagKind(), DC,
- StartLoc, IdLoc,
- ClassTemplate,
- TemplateArgs.data(),
- TemplateArgs.size(),
- /*PrevDecl=*/nullptr);
- 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()));
-
- // Add the specialization to this context.
- D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
- }
- Importer.Imported(D, D2);
-
- if (D->isCompleteDefinition() && ImportDefinition(D, D2))
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
return nullptr;
- return D2;
-}
+ TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten());
+ if (!TInfo && E->getTypeInfoAsWritten())
+ return nullptr;
-Decl *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
- // definition and map to that.
- VarDecl *Definition =
- cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition());
- if (Definition && Definition != D->getTemplatedDecl()) {
- Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate());
- if (!ImportedDef)
- return nullptr;
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return nullptr;
- return Importer.Imported(D, ImportedDef);
+ switch (E->getStmtClass()) {
+ case Stmt::CStyleCastExprClass: {
+ CStyleCastExpr *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()));
+ }
+
+ case Stmt::CXXFunctionalCastExprClass: {
+ CXXFunctionalCastExpr *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()));
+ }
+
+ case Stmt::ObjCBridgedCastExprClass: {
+ ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E);
+ return new (Importer.getToContext()) ObjCBridgedCastExpr(
+ Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(),
+ E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()),
+ TInfo, SubExpr);
+ }
+ default:
+ break; // just fall through
+ }
+
+ CXXNamedCastExpr *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;
}
+}
- // Import the major distinguishing characteristics of this variable template.
- DeclContext *DC, *LexicalDC;
- DeclarationName Name;
- SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) {
+ QualType T = Importer.Import(OE->getType());
+ if (T.isNull())
return nullptr;
- // We may already have a template of the same name; try to find and match it.
- assert(!DC->isFunctionOrMethod() &&
- "Variable templates cannot be declared at function scope");
- SmallVector<NamedDecl *, 4> ConflictingDecls;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
- continue;
+ SmallVector<OffsetOfNode, 4> Nodes;
+ for (int I = 0, E = OE->getNumComponents(); I < E; ++I) {
+ const OffsetOfNode &Node = OE->getComponent(I);
- Decl *Found = FoundDecls[I];
- if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
- if (IsStructuralMatch(D, FoundTemplate)) {
- // The variable templates structurally match; call it the same template.
- Importer.Imported(D->getTemplatedDecl(),
- FoundTemplate->getTemplatedDecl());
- return Importer.Imported(D, FoundTemplate);
- }
- }
+ switch (Node.getKind()) {
+ case OffsetOfNode::Array:
+ Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()),
+ Node.getArrayExprIndex(),
+ Importer.Import(Node.getLocEnd())));
+ break;
- ConflictingDecls.push_back(FoundDecls[I]);
+ case OffsetOfNode::Base: {
+ CXXBaseSpecifier *BS = Importer.Import(Node.getBase());
+ if (!BS && Node.getBase())
+ return nullptr;
+ Nodes.push_back(OffsetOfNode(BS));
+ break;
+ }
+ case OffsetOfNode::Field: {
+ FieldDecl *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())));
+ 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())));
+ break;
+ }
+ }
}
- if (!ConflictingDecls.empty()) {
- Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary,
- ConflictingDecls.data(),
- ConflictingDecls.size());
+ 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;
}
- if (!Name)
+ TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo());
+ if (!TInfo && OE->getTypeSourceInfo())
return nullptr;
- VarDecl *DTemplated = D->getTemplatedDecl();
+ return OffsetOfExpr::Create(Importer.getToContext(), T,
+ Importer.Import(OE->getOperatorLoc()),
+ TInfo, Nodes, Exprs,
+ Importer.Import(OE->getRParenLoc()));
+}
- // Import the type.
- QualType T = Importer.Import(DTemplated->getType());
+Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
+ QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
- // Create the declaration that is being templated.
- SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart());
- SourceLocation IdLoc = Importer.Import(DTemplated->getLocation());
- TypeSourceInfo *TInfo = Importer.Import(DTemplated->getTypeSourceInfo());
- VarDecl *D2Templated = VarDecl::Create(Importer.getToContext(), DC, StartLoc,
- IdLoc, Name.getAsIdentifierInfo(), T,
- TInfo, DTemplated->getStorageClass());
- D2Templated->setAccess(DTemplated->getAccess());
- D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
- D2Templated->setLexicalDeclContext(LexicalDC);
-
- // Importer.Imported(DTemplated, D2Templated);
- // LexicalDC->addDeclInternal(D2Templated);
-
- // Merge the initializer.
- if (ImportDefinition(DTemplated, D2Templated))
- return nullptr;
-
- // Create the variable template declaration itself.
- TemplateParameterList *TemplateParams =
- ImportTemplateParameterList(D->getTemplateParameters());
- if (!TemplateParams)
+ Expr *Operand = Importer.Import(E->getOperand());
+ if (!Operand)
return nullptr;
- VarTemplateDecl *D2 = VarTemplateDecl::Create(
- Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated);
- D2Templated->setDescribedVarTemplate(D2);
+ CanThrowResult CanThrow;
+ if (E->isValueDependent())
+ CanThrow = CT_Dependent;
+ else
+ CanThrow = E->getValue() ? CT_Can : CT_Cannot;
- D2->setAccess(D->getAccess());
- D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
+ return new (Importer.getToContext()) CXXNoexceptExpr(
+ T, Operand, CanThrow,
+ Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd()));
+}
- // Note the relationship between the variable templates.
- Importer.Imported(D, D2);
- Importer.Imported(DTemplated, D2Templated);
+Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
- if (DTemplated->isThisDeclarationADefinition() &&
- !D2Templated->isThisDeclarationADefinition()) {
- // FIXME: Import definition!
- }
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr && E->getSubExpr())
+ return nullptr;
- return D2;
+ return new (Importer.getToContext()) CXXThrowExpr(
+ SubExpr, T, Importer.Import(E->getThrowLoc()),
+ E->isThrownVariableInScope());
}
-Decl *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;
+Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+ ParmVarDecl *Param = cast_or_null<ParmVarDecl>(
+ Importer.Import(E->getParam()));
+ if (!Param)
+ return nullptr;
- return Importer.Imported(D, ImportedDef);
- }
+ return CXXDefaultArgExpr::Create(
+ Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param);
+}
- VarTemplateDecl *VarTemplate = cast_or_null<VarTemplateDecl>(
- Importer.Import(D->getSpecializedTemplate()));
- if (!VarTemplate)
+Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
return nullptr;
- // Import the context of this declaration.
- DeclContext *DC = VarTemplate->getDeclContext();
- if (!DC)
+ TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo());
+ if (!TypeInfo)
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());
+ return new (Importer.getToContext()) CXXScalarValueInitExpr(
+ T, TypeInfo, Importer.Import(E->getRParenLoc()));
+}
- // Import template arguments.
- SmallVector<TemplateArgument, 2> TemplateArgs;
- if (ImportTemplateArguments(D->getTemplateArgs().data(),
- D->getTemplateArgs().size(), TemplateArgs))
+Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
return nullptr;
- // Try to find an existing specialization with these template arguments.
- void *InsertPos = nullptr;
- VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization(
- TemplateArgs, InsertPos);
- if (D2) {
- // We already have a variable template specialization with these template
- // arguments.
-
- // FIXME: Check for specialization vs. instantiation errors.
+ auto *Dtor = cast_or_null<CXXDestructorDecl>(
+ Importer.Import(const_cast<CXXDestructorDecl *>(
+ E->getTemporary()->getDestructor())));
+ if (!Dtor)
+ return nullptr;
- if (VarDecl *FoundDef = D2->getDefinition()) {
- if (!D->isThisDeclarationADefinition() ||
- IsStructuralMatch(D, FoundDef)) {
- // The record types structurally match, or the "from" translation
- // unit only had a forward declaration anyway; call it the same
- // variable.
- return Importer.Imported(D, FoundDef);
- }
- }
- } else {
+ ASTContext &ToCtx = Importer.getToContext();
+ CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor);
+ return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr);
+}
- // Import the type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
+ QualType T = Importer.Import(CE->getType());
+ if (T.isNull())
+ return nullptr;
- // Create a new specialization.
- D2 = VarTemplateSpecializationDecl::Create(
- Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo,
- D->getStorageClass(), TemplateArgs.data(), TemplateArgs.size());
- D2->setSpecializationKind(D->getSpecializationKind());
- D2->setTemplateArgsInfo(D->getTemplateArgsInfo());
+ SmallVector<Expr *, 8> Args(CE->getNumArgs());
+ if (ImportContainerChecked(CE->arguments(), Args))
+ return nullptr;
- // Add this specialization to the class template.
- VarTemplate->AddSpecialization(D2, InsertPos);
+ auto *Ctor = cast_or_null<CXXConstructorDecl>(
+ Importer.Import(CE->getConstructor()));
+ if (!Ctor)
+ return nullptr;
- // Import the qualifier, if any.
- D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+ return CXXTemporaryObjectExpr::Create(
+ Importer.getToContext(), T,
+ Importer.Import(CE->getLocStart()),
+ Ctor,
+ CE->isElidable(),
+ Args,
+ CE->hadMultipleCandidates(),
+ CE->isListInitialization(),
+ CE->isStdInitListInitialization(),
+ CE->requiresZeroInitialization(),
+ CE->getConstructionKind(),
+ Importer.Import(CE->getParenOrBraceRange()));
+}
+
+Expr *
+ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
- // Add the specialization to this context.
- D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
- }
- Importer.Imported(D, D2);
+ Expr *TempE = Importer.Import(E->GetTemporaryExpr());
+ if (!TempE)
+ return nullptr;
- if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2))
+ ValueDecl *ExtendedBy = cast_or_null<ValueDecl>(
+ Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl())));
+ if (!ExtendedBy && E->getExtendingDecl())
return nullptr;
- return D2;
+ auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr(
+ T, TempE, E->isBoundToLvalueReference());
+
+ // FIXME: Should ManglingNumber get numbers associated with 'to' context?
+ ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber());
+ return ToMTE;
}
-//----------------------------------------------------------------------------
-// Import Statements
-//----------------------------------------------------------------------------
+Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
+ QualType T = Importer.Import(CE->getType());
+ if (T.isNull())
+ return nullptr;
-Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
- Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
- << S->getStmtClassName();
- return nullptr;
-}
+ SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs());
+ if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs))
+ return nullptr;
-//----------------------------------------------------------------------------
-// Import Expressions
-//----------------------------------------------------------------------------
-Expr *ASTNodeImporter::VisitExpr(Expr *E) {
- Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node)
- << E->getStmtClassName();
- return nullptr;
-}
+ FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(CE->getOperatorNew()));
+ if (!OperatorNewDecl && CE->getOperatorNew())
+ return nullptr;
-Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
- ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl()));
- if (!ToD)
+ FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(CE->getOperatorDelete()));
+ if (!OperatorDeleteDecl && CE->getOperatorDelete())
return nullptr;
- NamedDecl *FoundD = nullptr;
- if (E->getDecl() != E->getFoundDecl()) {
- FoundD = cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl()));
- if (!FoundD)
- return nullptr;
- }
-
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
+ Expr *ToInit = Importer.Import(CE->getInitializer());
+ if (!ToInit && CE->getInitializer())
return nullptr;
- DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
- Importer.Import(E->getQualifierLoc()),
- Importer.Import(E->getTemplateKeywordLoc()),
- ToD,
- E->refersToEnclosingLocal(),
- Importer.Import(E->getLocation()),
- T, E->getValueKind(),
- FoundD,
- /*FIXME:TemplateArgs=*/nullptr);
- if (E->hadMultipleCandidates())
- DRE->setHadMultipleCandidates(true);
- return DRE;
+ TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo());
+ if (!TInfo)
+ return nullptr;
+
+ Expr *ToArrSize = Importer.Import(CE->getArraySize());
+ if (!ToArrSize && CE->getArraySize())
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXNewExpr(
+ Importer.getToContext(),
+ CE->isGlobalNew(),
+ OperatorNewDecl, OperatorDeleteDecl,
+ CE->passAlignment(),
+ CE->doesUsualArrayDeleteWantSize(),
+ PlacementArgs,
+ Importer.Import(CE->getTypeIdParens()),
+ ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo,
+ Importer.Import(CE->getSourceRange()),
+ Importer.Import(CE->getDirectInitRange()));
}
-Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
+Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
- return IntegerLiteral::Create(Importer.getToContext(),
- E->getValue(), T,
- Importer.Import(E->getLocation()));
+ FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(E->getOperatorDelete()));
+ if (!OperatorDeleteDecl && E->getOperatorDelete())
+ return nullptr;
+
+ Expr *ToArg = Importer.Import(E->getArgument());
+ if (!ToArg && E->getArgument())
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXDeleteExpr(
+ T, E->isGlobalDelete(),
+ E->isArrayForm(),
+ E->isArrayFormAsWritten(),
+ E->doesUsualArrayDeleteWantSize(),
+ OperatorDeleteDecl,
+ ToArg,
+ Importer.Import(E->getLocStart()));
}
-Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
+Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
- return new (Importer.getToContext()) CharacterLiteral(E->getValue(),
- E->getKind(), T,
- Importer.Import(E->getLocation()));
+ CXXConstructorDecl *ToCCD =
+ dyn_cast_or_null<CXXConstructorDecl>(Importer.Import(E->getConstructor()));
+ if (!ToCCD)
+ return nullptr;
+
+ SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
+ if (ImportContainerChecked(E->arguments(), ToArgs))
+ return nullptr;
+
+ return CXXConstructExpr::Create(Importer.getToContext(), T,
+ Importer.Import(E->getLocation()),
+ ToCCD, E->isElidable(),
+ ToArgs, E->hadMultipleCandidates(),
+ E->isListInitialization(),
+ E->isStdInitListInitialization(),
+ E->requiresZeroInitialization(),
+ E->getConstructionKind(),
+ Importer.Import(E->getParenOrBraceRange()));
}
-Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
+Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) {
+ Expr *SubExpr = Importer.Import(EWC->getSubExpr());
+ if (!SubExpr && EWC->getSubExpr())
return nullptr;
- return new (Importer.getToContext())
- ParenExpr(Importer.Import(E->getLParen()),
- Importer.Import(E->getRParen()),
- SubExpr);
+ 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;
+
+ return ExprWithCleanups::Create(Importer.getToContext(),
+ SubExpr, EWC->cleanupsHaveSideEffects(),
+ Objs);
}
-Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
+Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
-
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
+
+ Expr *ToFn = Importer.Import(E->getCallee());
+ if (!ToFn)
+ return nullptr;
+
+ SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
+ if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
- return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(),
- T, E->getValueKind(),
- E->getObjectKind(),
- Importer.Import(E->getOperatorLoc()));
+ return new (Importer.getToContext()) CXXMemberCallExpr(
+ Importer.getToContext(), ToFn, ToArgs, T, E->getValueKind(),
+ Importer.Import(E->getRParenLoc()));
}
-Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(
- UnaryExprOrTypeTraitExpr *E) {
- QualType ResultType = Importer.Import(E->getType());
+Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
- if (E->isArgumentType()) {
- TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo());
- if (!TInfo)
- return nullptr;
+ return new (Importer.getToContext())
+ CXXThisExpr(Importer.Import(E->getLocation()), T, E->isImplicit());
+}
- return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
- TInfo, ResultType,
- Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getRParenLoc()));
- }
-
- Expr *SubExpr = Importer.Import(E->getArgumentExpr());
- if (!SubExpr)
+Expr *ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
return nullptr;
-
- return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
- SubExpr, ResultType,
- Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getRParenLoc()));
+
+ return new (Importer.getToContext())
+ CXXBoolLiteralExpr(E->getValue(), T, Importer.Import(E->getLocation()));
}
-Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
+
+Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
- Expr *LHS = Importer.Import(E->getLHS());
- if (!LHS)
+ Expr *ToBase = Importer.Import(E->getBase());
+ if (!ToBase && E->getBase())
return nullptr;
- Expr *RHS = Importer.Import(E->getRHS());
- if (!RHS)
+ ValueDecl *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl()));
+ if (!ToMember && E->getMemberDecl())
return nullptr;
- return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(),
- T, E->getValueKind(),
- E->getObjectKind(),
- Importer.Import(E->getOperatorLoc()),
- E->isFPContractable());
+ DeclAccessPair ToFoundDecl = DeclAccessPair::make(
+ dyn_cast<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())),
+ E->getFoundDecl().getAccess());
+
+ DeclarationNameInfo ToMemberNameInfo(
+ Importer.Import(E->getMemberNameInfo().getName()),
+ Importer.Import(E->getMemberNameInfo().getLoc()));
+
+ if (E->hasExplicitTemplateArgs()) {
+ return nullptr; // FIXME: handle template arguments
+ }
+
+ return MemberExpr::Create(Importer.getToContext(), ToBase,
+ E->isArrow(),
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getQualifierLoc()),
+ Importer.Import(E->getTemplateKeywordLoc()),
+ ToMember, ToFoundDecl, ToMemberNameInfo,
+ nullptr, T, E->getValueKind(),
+ E->getObjectKind());
}
-Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
- QualType CompLHSType = Importer.Import(E->getComputationLHSType());
- if (CompLHSType.isNull())
+ Expr *ToCallee = Importer.Import(E->getCallee());
+ if (!ToCallee && E->getCallee())
return nullptr;
- QualType CompResultType = Importer.Import(E->getComputationResultType());
- if (CompResultType.isNull())
- return nullptr;
+ unsigned NumArgs = E->getNumArgs();
- Expr *LHS = Importer.Import(E->getLHS());
- if (!LHS)
+ llvm::SmallVector<Expr *, 2> ToArgs(NumArgs);
+
+ for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) {
+ Expr *FromArg = E->getArg(ai);
+ Expr *ToArg = Importer.Import(FromArg);
+ if (!ToArg)
+ return nullptr;
+ ToArgs[ai] = ToArg;
+ }
+
+ Expr **ToArgs_Copied = new (Importer.getToContext())
+ Expr*[NumArgs];
+
+ for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai)
+ ToArgs_Copied[ai] = ToArgs[ai];
+
+ return new (Importer.getToContext())
+ CallExpr(Importer.getToContext(), ToCallee,
+ llvm::makeArrayRef(ToArgs_Copied, NumArgs), T, E->getValueKind(),
+ Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
+ QualType T = Importer.Import(ILE->getType());
+ if (T.isNull())
return nullptr;
- Expr *RHS = Importer.Import(E->getRHS());
- if (!RHS)
+ llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
+ if (ImportContainerChecked(ILE->inits(), Exprs))
return nullptr;
- return new (Importer.getToContext())
- CompoundAssignOperator(LHS, RHS, E->getOpcode(),
- T, E->getValueKind(),
- E->getObjectKind(),
- CompLHSType, CompResultType,
- Importer.Import(E->getOperatorLoc()),
- E->isFPContractable());
+ ASTContext &ToCtx = Importer.getToContext();
+ InitListExpr *To = new (ToCtx) InitListExpr(
+ ToCtx, Importer.Import(ILE->getLBraceLoc()),
+ Exprs, Importer.Import(ILE->getLBraceLoc()));
+ To->setType(T);
+
+ if (ILE->hasArrayFiller()) {
+ Expr *Filler = Importer.Import(ILE->getArrayFiller());
+ if (!Filler)
+ return nullptr;
+ To->setArrayFiller(Filler);
+ }
+
+ if (FieldDecl *FromFD = ILE->getInitializedFieldInUnion()) {
+ FieldDecl *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD));
+ if (!ToFD)
+ return nullptr;
+ To->setInitializedFieldInUnion(ToFD);
+ }
+
+ if (InitListExpr *SyntForm = ILE->getSyntacticForm()) {
+ InitListExpr *ToSyntForm = cast_or_null<InitListExpr>(
+ Importer.Import(SyntForm));
+ if (!ToSyntForm)
+ return nullptr;
+ To->setSyntacticForm(ToSyntForm);
+ }
+
+ To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator());
+ To->setValueDependent(ILE->isValueDependent());
+ To->setInstantiationDependent(ILE->isInstantiationDependent());
+
+ return To;
}
-static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
- if (E->path_empty()) return false;
+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;
+
+ Expr *ToSubExpr = Importer.Import(E->getSubExpr());
+ if (!ToSubExpr && E->getSubExpr())
+ return nullptr;
- // TODO: import cast paths
- return true;
+ return new (Importer.getToContext())
+ ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr);
}
-Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
+Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+ QualType ToType = Importer.Import(E->getType());
+ if (ToType.isNull())
return nullptr;
+ return new (Importer.getToContext()) ArrayInitIndexExpr(ToType);
+}
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
+Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
+ FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>(
+ Importer.Import(DIE->getField()));
+ if (!ToField && DIE->getField())
return nullptr;
+ return CXXDefaultInitExpr::Create(
+ Importer.getToContext(), Importer.Import(DIE->getLocStart()), ToField);
+}
+
+Expr *ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+ QualType ToType = Importer.Import(E->getType());
+ if (ToType.isNull() && !E->getType().isNull())
+ return nullptr;
+ 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;
-
- return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
- SubExpr, &BasePath, E->getValueKind());
+ TypeSourceInfo *ToWritten = Importer.Import(E->getTypeInfoAsWritten());
+ SourceLocation ToOperatorLoc = Importer.Import(E->getOperatorLoc());
+ SourceLocation ToRParenLoc = Importer.Import(E->getRParenLoc());
+ SourceRange ToAngleBrackets = Importer.Import(E->getAngleBrackets());
+
+ if (isa<CXXStaticCastExpr>(E)) {
+ return CXXStaticCastExpr::Create(
+ Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
+ ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
+ } else if (isa<CXXDynamicCastExpr>(E)) {
+ return CXXDynamicCastExpr::Create(
+ Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
+ ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
+ } else if (isa<CXXReinterpretCastExpr>(E)) {
+ return CXXReinterpretCastExpr::Create(
+ Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
+ ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
+ } else {
+ return nullptr;
+ }
}
-Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
+
+Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
+ SubstNonTypeTemplateParmExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
+ NonTypeTemplateParmDecl *Param = cast_or_null<NonTypeTemplateParmDecl>(
+ Importer.Import(E->getParameter()));
+ if (!Param)
return nullptr;
- TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten());
- if (!TInfo && E->getTypeInfoAsWritten())
+ Expr *Replacement = Importer.Import(E->getReplacement());
+ if (!Replacement)
return nullptr;
- CXXCastPath BasePath;
- if (ImportCastPath(E, BasePath))
- return nullptr;
+ return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
+ T, E->getValueKind(), Importer.Import(E->getExprLoc()), Param,
+ Replacement);
+}
- return CStyleCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), E->getCastKind(),
- SubExpr, &BasePath, TInfo,
- Importer.Import(E->getLParenLoc()),
- Importer.Import(E->getRParenLoc()));
+void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
+ CXXMethodDecl *FromMethod) {
+ for (auto *FromOverriddenMethod : FromMethod->overridden_methods())
+ ToMethod->addOverriddenMethod(
+ cast<CXXMethodDecl>(Importer.Import(const_cast<CXXMethodDecl*>(
+ FromOverriddenMethod))));
}
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
return nullptr;
return ToContext.getTrivialTypeSourceInfo(T,
- FromTSI->getTypeLoc().getLocStart());
+ Import(FromTSI->getTypeLoc().getLocStart()));
+}
+
+Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
+ llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
+ if (Pos != ImportedDecls.end()) {
+ Decl *ToD = Pos->second;
+ ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD);
+ return ToD;
+ } else {
+ return nullptr;
+ }
}
Decl *ASTImporter::Import(Decl *FromD) {
case NestedNameSpecifier::Namespace:
if (NamespaceDecl *NS =
- cast<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) {
+ cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) {
return NestedNameSpecifier::Create(ToContext, prefix, NS);
}
return nullptr;
case NestedNameSpecifier::NamespaceAlias:
if (NamespaceAliasDecl *NSAD =
- cast<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) {
+ cast_or_null<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) {
return NestedNameSpecifier::Create(ToContext, prefix, NSAD);
}
return nullptr;
case NestedNameSpecifier::Super:
if (CXXRecordDecl *RD =
- cast<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
+ cast_or_null<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
return NestedNameSpecifier::SuperSpecifier(ToContext, RD);
}
return nullptr;
}
NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
- // FIXME: Implement!
- return NestedNameSpecifierLoc();
+ // Copied from NestedNameSpecifier mostly.
+ SmallVector<NestedNameSpecifierLoc , 8> NestedNames;
+ NestedNameSpecifierLoc NNS = FromNNS;
+
+ // Push each of the nested-name-specifiers's onto a stack for
+ // serialization in reverse order.
+ while (NNS) {
+ NestedNames.push_back(NNS);
+ NNS = NNS.getPrefix();
+ }
+
+ NestedNameSpecifierLocBuilder Builder;
+
+ while (!NestedNames.empty()) {
+ NNS = NestedNames.pop_back_val();
+ NestedNameSpecifier *Spec = Import(NNS.getNestedNameSpecifier());
+ if (!Spec)
+ return NestedNameSpecifierLoc();
+
+ NestedNameSpecifier::SpecifierKind Kind = Spec->getKind();
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier:
+ Builder.Extend(getToContext(),
+ Spec->getAsIdentifier(),
+ Import(NNS.getLocalBeginLoc()),
+ Import(NNS.getLocalEndLoc()));
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ Builder.Extend(getToContext(),
+ Spec->getAsNamespace(),
+ Import(NNS.getLocalBeginLoc()),
+ Import(NNS.getLocalEndLoc()));
+ break;
+
+ case NestedNameSpecifier::NamespaceAlias:
+ Builder.Extend(getToContext(),
+ Spec->getAsNamespaceAlias(),
+ Import(NNS.getLocalBeginLoc()),
+ Import(NNS.getLocalEndLoc()));
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo(
+ QualType(Spec->getAsType(), 0));
+ Builder.Extend(getToContext(),
+ Import(NNS.getLocalBeginLoc()),
+ TSI->getTypeLoc(),
+ Import(NNS.getLocalEndLoc()));
+ break;
+ }
+
+ case NestedNameSpecifier::Global:
+ Builder.MakeGlobal(getToContext(), Import(NNS.getLocalBeginLoc()));
+ break;
+
+ case NestedNameSpecifier::Super: {
+ SourceRange ToRange = Import(NNS.getSourceRange());
+ Builder.MakeSuper(getToContext(),
+ Spec->getAsRecordDecl(),
+ ToRange.getBegin(),
+ ToRange.getEnd());
+ }
+ }
+ }
+
+ return Builder.getWithLocInContext(getToContext());
}
TemplateName ASTImporter::Import(TemplateName From) {
SourceManager &FromSM = FromContext.getSourceManager();
- // For now, map everything down to its spelling location, so that we
+ // For now, map everything down to its file location, so that we
// don't have to import macro expansions.
// FIXME: Import macro expansions!
- FromLoc = FromSM.getSpellingLoc(FromLoc);
+ FromLoc = FromSM.getFileLoc(FromLoc);
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
SourceManager &ToSM = ToContext.getSourceManager();
- return ToSM.getLocForStartOfFile(Import(Decomposed.first))
- .getLocWithOffset(Decomposed.second);
+ FileID ToFileID = Import(Decomposed.first);
+ if (ToFileID.isInvalid())
+ return SourceLocation();
+ SourceLocation ret = ToSM.getLocForStartOfFile(ToFileID)
+ .getLocWithOffset(Decomposed.second);
+ return ret;
}
SourceRange ASTImporter::Import(SourceRange FromRange) {
// Map the FileID for to the "to" source manager.
FileID ToID;
const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
- if (Cache->OrigEntry) {
+ if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
// disk again
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
// than mmap the files several times.
const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName());
+ if (!Entry)
+ return FileID();
ToID = ToSM.createFileID(Entry, ToIncludeLoc,
FromSLoc.getFile().getFileCharacteristic());
} else {
return ToID;
}
+CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
+ Expr *ToExpr = Import(From->getInit());
+ if (!ToExpr && From->getInit())
+ return nullptr;
+
+ if (From->isBaseInitializer()) {
+ TypeSourceInfo *ToTInfo = Import(From->getTypeSourceInfo());
+ if (!ToTInfo && From->getTypeSourceInfo())
+ return nullptr;
+
+ return new (ToContext) CXXCtorInitializer(
+ ToContext, ToTInfo, From->isBaseVirtual(), Import(From->getLParenLoc()),
+ ToExpr, Import(From->getRParenLoc()),
+ From->isPackExpansion() ? Import(From->getEllipsisLoc())
+ : SourceLocation());
+ } else if (From->isMemberInitializer()) {
+ FieldDecl *ToField =
+ llvm::cast_or_null<FieldDecl>(Import(From->getMember()));
+ if (!ToField && From->getMember())
+ return nullptr;
+
+ return new (ToContext) CXXCtorInitializer(
+ ToContext, ToField, Import(From->getMemberLocation()),
+ Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()));
+ } else if (From->isIndirectMemberInitializer()) {
+ IndirectFieldDecl *ToIField = llvm::cast_or_null<IndirectFieldDecl>(
+ Import(From->getIndirectMember()));
+ if (!ToIField && From->getIndirectMember())
+ return nullptr;
+
+ return new (ToContext) CXXCtorInitializer(
+ ToContext, ToIField, Import(From->getMemberLocation()),
+ Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()));
+ } else if (From->isDelegatingInitializer()) {
+ TypeSourceInfo *ToTInfo = Import(From->getTypeSourceInfo());
+ if (!ToTInfo && From->getTypeSourceInfo())
+ return nullptr;
+
+ return new (ToContext)
+ CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()),
+ ToExpr, Import(From->getRParenLoc()));
+ } else {
+ return nullptr;
+ }
+}
+
+
+CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
+ auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
+ if (Pos != ImportedCXXBaseSpecifiers.end())
+ return Pos->second;
+
+ CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier(
+ Import(BaseSpec->getSourceRange()),
+ BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(),
+ BaseSpec->getAccessSpecifierAsWritten(),
+ Import(BaseSpec->getTypeSourceInfo()),
+ Import(BaseSpec->getEllipsisLoc()));
+ ImportedCXXBaseSpecifiers[BaseSpec] = Imported;
+ return Imported;
+}
+
void ASTImporter::ImportDefinition(Decl *From) {
Decl *To = Import(From);
if (!To)
ToContext.getCanonicalType(T));
}
+ case DeclarationName::CXXDeductionGuideName: {
+ TemplateDecl *Template = cast_or_null<TemplateDecl>(
+ Import(FromName.getCXXDeductionGuideTemplate()));
+ if (!Template)
+ return DeclarationName();
+ return ToContext.DeclarationNames.getCXXDeductionGuideName(Template);
+ }
+
case DeclarationName::CXXConversionFunctionName: {
QualType T = Import(FromName.getCXXNameType());
if (T.isNull())
if (!FromId)
return nullptr;
- return &ToContext.Idents.get(FromId->getName());
+ IdentifierInfo *ToId = &ToContext.Idents.get(FromId->getName());
+
+ if (!ToId->getBuiltinID() && FromId->getBuiltinID())
+ ToId->setBuiltinID(FromId->getBuiltinID());
+
+ return ToId;
}
Selector ASTImporter::Import(Selector FromSel) {
}
Decl *ASTImporter::Imported(Decl *From, Decl *To) {
+ if (From->hasAttrs()) {
+ for (Attr *FromAttr : From->getAttrs())
+ To->addAttr(FromAttr->clone(To->getASTContext()));
+ }
+ if (From->isUsed()) {
+ To->setIsUsed();
+ }
+ if (From->isImplicit()) {
+ To->setImplicit();
+ }
ImportedDecls[From] = To;
return To;
}
= ImportedTypes.find(From.getTypePtr());
if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To))
return true;
-
+
StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls,
false, Complain);
return Ctx.IsStructurallyEquivalent(From, To);