From ecd30bdd0122f58936d648ab1f457370e84c0662 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Fri, 28 Apr 2017 00:31:30 +0000 Subject: [ASTImporter] Move structural equivalence context to its own file. NFCI Create a header and impl file for the structural equivalence context. This is to allow other users outside clang importer. NFCI Differential Revision: https://reviews.llvm.org/D31777 rdar://problem/30167717 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@301604 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 1444 +---------------------------------------------- 1 file changed, 31 insertions(+), 1413 deletions(-) (limited to 'lib/AST/ASTImporter.cpp') diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 95492825eb..4fb6051d6f 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -14,6 +14,7 @@ #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" @@ -321,1396 +322,12 @@ namespace clang { }; } -using namespace clang; - -//---------------------------------------------------------------------------- -// Structural Equivalence -//---------------------------------------------------------------------------- - -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 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 DeclsToCheck; - - /// \brief Declaration (from, to) pairs that are known not to be equivalent - /// (which we have already complained about). - llvm::DenseSet > &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 > &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); - } - - 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); - } - }; -} - -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - QualType T1, QualType T2); -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - Decl *D1, Decl *D2); -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - const TemplateArgument &Arg1, - const TemplateArgument &Arg2); - -/// \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; -} - -/// \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(); -} - -/// \brief Determine whether two nested-name-specifiers are equivalent. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - NestedNameSpecifier *NNS1, - NestedNameSpecifier *NNS2) { - if (NNS1->getKind() != NNS2->getKind()) - return false; - - NestedNameSpecifier *Prefix1 = NNS1->getPrefix(), - *Prefix2 = NNS2->getPrefix(); - if ((bool)Prefix1 != (bool)Prefix2) - return false; - - if (Prefix1) - if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2)) - return false; - - switch (NNS1->getKind()) { - case NestedNameSpecifier::Identifier: - return IsStructurallyEquivalent(NNS1->getAsIdentifier(), - NNS2->getAsIdentifier()); - case NestedNameSpecifier::Namespace: - return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(), - NNS2->getAsNamespace()); - case NestedNameSpecifier::NamespaceAlias: - return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(), - NNS2->getAsNamespaceAlias()); - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0), - QualType(NNS2->getAsType(), 0)); - case NestedNameSpecifier::Global: - return true; - case NestedNameSpecifier::Super: - return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(), - NNS2->getAsRecordDecl()); - } - return false; -} - -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - const TemplateName &N1, - const TemplateName &N2) { - if (N1.getKind() != N2.getKind()) - return false; - switch (N1.getKind()) { - case TemplateName::Template: - return IsStructurallyEquivalent(Context, N1.getAsTemplateDecl(), - N2.getAsTemplateDecl()); - - case TemplateName::OverloadedTemplate: { - OverloadedTemplateStorage *OS1 = N1.getAsOverloadedTemplate(), - *OS2 = N2.getAsOverloadedTemplate(); - OverloadedTemplateStorage::iterator I1 = OS1->begin(), I2 = OS2->begin(), - E1 = OS1->end(), E2 = OS2->end(); - for (; I1 != E1 && I2 != E2; ++I1, ++I2) - if (!IsStructurallyEquivalent(Context, *I1, *I2)) - return false; - return I1 == E1 && I2 == E2; - } - - case TemplateName::QualifiedTemplate: { - QualifiedTemplateName *QN1 = N1.getAsQualifiedTemplateName(), - *QN2 = N2.getAsQualifiedTemplateName(); - return IsStructurallyEquivalent(Context, QN1->getDecl(), QN2->getDecl()) && - IsStructurallyEquivalent(Context, QN1->getQualifier(), - QN2->getQualifier()); - } - - case TemplateName::DependentTemplate: { - DependentTemplateName *DN1 = N1.getAsDependentTemplateName(), - *DN2 = N2.getAsDependentTemplateName(); - if (!IsStructurallyEquivalent(Context, DN1->getQualifier(), - DN2->getQualifier())) - return false; - if (DN1->isIdentifier() && DN2->isIdentifier()) - return IsStructurallyEquivalent(DN1->getIdentifier(), - DN2->getIdentifier()); - else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator()) - return DN1->getOperator() == DN2->getOperator(); - return false; - } - - case TemplateName::SubstTemplateTemplateParm: { - SubstTemplateTemplateParmStorage *TS1 = N1.getAsSubstTemplateTemplateParm(), - *TS2 = N2.getAsSubstTemplateTemplateParm(); - return IsStructurallyEquivalent(Context, TS1->getParameter(), - TS2->getParameter()) && - IsStructurallyEquivalent(Context, TS1->getReplacement(), - TS2->getReplacement()); - } - case TemplateName::SubstTemplateTemplateParmPack: { - SubstTemplateTemplateParmPackStorage - *P1 = N1.getAsSubstTemplateTemplateParmPack(), - *P2 = N2.getAsSubstTemplateTemplateParmPack(); - return IsStructurallyEquivalent(Context, P1->getArgumentPack(), - P2->getArgumentPack()) && - IsStructurallyEquivalent(Context, P1->getParameterPack(), - P2->getParameterPack()); - } - } - return false; -} - -/// \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; - - switch (Arg1.getKind()) { - case TemplateArgument::Null: - return true; - - case TemplateArgument::Type: - return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType()); - - case TemplateArgument::Integral: - if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(), - Arg2.getIntegralType())) - return false; - - return llvm::APSInt::isSameValue(Arg1.getAsIntegral(), Arg2.getAsIntegral()); - - case TemplateArgument::Declaration: - return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl()); - - case TemplateArgument::NullPtr: - return true; // FIXME: Is this correct? - - case TemplateArgument::Template: - return IsStructurallyEquivalent(Context, - Arg1.getAsTemplate(), - Arg2.getAsTemplate()); - - case TemplateArgument::TemplateExpansion: - return IsStructurallyEquivalent(Context, - Arg1.getAsTemplateOrTemplatePattern(), - Arg2.getAsTemplateOrTemplatePattern()); - - 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"); -} - -/// \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; - - return true; -} - -/// \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(T1)->getKind() != cast(T2)->getKind()) - return false; - break; - - case Type::Complex: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getElementType(), - cast(T2)->getElementType())) - return false; - break; - - case Type::Adjusted: - case Type::Decayed: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getOriginalType(), - cast(T2)->getOriginalType())) - return false; - break; - - case Type::Pointer: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getPointeeType(), - cast(T2)->getPointeeType())) - return false; - break; - - case Type::BlockPointer: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getPointeeType(), - cast(T2)->getPointeeType())) - return false; - break; - - case Type::LValueReference: - case Type::RValueReference: { - const ReferenceType *Ref1 = cast(T1); - const ReferenceType *Ref2 = cast(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(T1); - const MemberPointerType *MemPtr2 = cast(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(T1); - const ConstantArrayType *Array2 = cast(T2); - if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize())) - return false; - - if (!IsArrayStructurallyEquivalent(Context, Array1, Array2)) - return false; - break; - } - - case Type::IncompleteArray: - if (!IsArrayStructurallyEquivalent(Context, - cast(T1), - cast(T2))) - return false; - break; - - case Type::VariableArray: { - const VariableArrayType *Array1 = cast(T1); - const VariableArrayType *Array2 = cast(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(T1); - const DependentSizedArrayType *Array2 = cast(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(T1); - const DependentSizedExtVectorType *Vec2 - = cast(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(T1); - const VectorType *Vec2 = cast(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(T1); - const FunctionProtoType *Proto2 = cast(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(T1); - const FunctionType *Function2 = cast(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(T1)->getDecl(), - cast(T2)->getDecl())) - return false; - - break; - - case Type::Attributed: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getModifiedType(), - cast(T2)->getModifiedType())) - return false; - if (!IsStructurallyEquivalent(Context, - cast(T1)->getEquivalentType(), - cast(T2)->getEquivalentType())) - return false; - break; - - case Type::Paren: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getInnerType(), - cast(T2)->getInnerType())) - return false; - break; - - case Type::Typedef: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getDecl(), - cast(T2)->getDecl())) - return false; - break; - - case Type::TypeOfExpr: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getUnderlyingExpr(), - cast(T2)->getUnderlyingExpr())) - return false; - break; - - case Type::TypeOf: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getUnderlyingType(), - cast(T2)->getUnderlyingType())) - return false; - break; - - case Type::UnaryTransform: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getUnderlyingType(), - cast(T1)->getUnderlyingType())) - return false; - break; - - case Type::Decltype: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getUnderlyingExpr(), - cast(T2)->getUnderlyingExpr())) - return false; - break; - - case Type::Auto: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getDeducedType(), - cast(T2)->getDeducedType())) - return false; - break; - - case Type::DeducedTemplateSpecialization: { - auto *DT1 = cast(T1); - auto *DT2 = cast(T2); - if (!IsStructurallyEquivalent(Context, - DT1->getTemplateName(), - DT2->getTemplateName())) - return false; - if (!IsStructurallyEquivalent(Context, - DT1->getDeducedType(), - DT2->getDeducedType())) - return false; - break; - } - - case Type::Record: - case Type::Enum: - if (!IsStructurallyEquivalent(Context, - cast(T1)->getDecl(), - cast(T2)->getDecl())) - return false; - break; - - case Type::TemplateTypeParm: { - const TemplateTypeParmType *Parm1 = cast(T1); - const TemplateTypeParmType *Parm2 = cast(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(T1); - const SubstTemplateTypeParmType *Subst2 - = cast(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(T1); - const SubstTemplateTypeParmPackType *Subst2 - = cast(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(T1); - const TemplateSpecializationType *Spec2 - = cast(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(T1); - const ElaboratedType *Elab2 = cast(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(T1); - const InjectedClassNameType *Inj2 = cast(T2); - if (!IsStructurallyEquivalent(Context, - Inj1->getInjectedSpecializationType(), - Inj2->getInjectedSpecializationType())) - return false; - break; - } - - case Type::DependentName: { - const DependentNameType *Typename1 = cast(T1); - const DependentNameType *Typename2 = cast(T2); - if (!IsStructurallyEquivalent(Context, - Typename1->getQualifier(), - Typename2->getQualifier())) - return false; - if (!IsStructurallyEquivalent(Typename1->getIdentifier(), - Typename2->getIdentifier())) - return false; - - break; - } - - case Type::DependentTemplateSpecialization: { - const DependentTemplateSpecializationType *Spec1 = - cast(T1); - const DependentTemplateSpecializationType *Spec2 = - cast(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(T1)->getPattern(), - cast(T2)->getPattern())) - return false; - break; - - case Type::ObjCInterface: { - const ObjCInterfaceType *Iface1 = cast(T1); - const ObjCInterfaceType *Iface2 = cast(T2); - if (!IsStructurallyEquivalent(Context, - Iface1->getDecl(), Iface2->getDecl())) - return false; - break; - } - - case Type::ObjCTypeParam: { - const ObjCTypeParamType *Obj1 = cast(T1); - const ObjCTypeParamType *Obj2 = cast(T2); - if (!IsStructurallyEquivalent(Context, Obj1->getDecl(), - Obj2->getDecl())) - 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; - } - case Type::ObjCObject: { - const ObjCObjectType *Obj1 = cast(T1); - const ObjCObjectType *Obj2 = cast(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; - } - - case Type::ObjCObjectPointer: { - const ObjCObjectPointerType *Ptr1 = cast(T1); - const ObjCObjectPointerType *Ptr2 = cast(T2); - if (!IsStructurallyEquivalent(Context, - Ptr1->getPointeeType(), - Ptr2->getPointeeType())) - return false; - break; - } - - case Type::Atomic: { - if (!IsStructurallyEquivalent(Context, - cast(T1)->getValueType(), - cast(T2)->getValueType())) - return false; - break; - } - - case Type::Pipe: { - if (!IsStructurallyEquivalent(Context, - cast(T1)->getElementType(), - cast(T2)->getElementType())) - return false; - break; - } - - } // end switch - - return true; -} - -/// \brief Determine structural equivalence of two fields. -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - FieldDecl *Field1, FieldDecl *Field2) { - RecordDecl *Owner2 = cast(Field2->getDeclContext()); - - // 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()->getDecl(); - RecordDecl *D2 = Field2->getType()->castAs()->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; - - 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; - } - - 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; - } - - 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 true; -} - -/// \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 findUntaggedStructOrUnionIndex(RecordDecl *Anon) { - ASTContext &Context = Anon->getASTContext(); - QualType AnonTy = Context.getRecordType(Anon); - - RecordDecl *Owner = dyn_cast(Anon->getDeclContext()); - if (!Owner) - return None; - - unsigned Index = 0; - for (const auto *D : Owner->noload_decls()) { - const auto *F = dyn_cast(D); - if (!F) - continue; - - if (F->isAnonymousStructOrUnion()) { - if (Context.hasSameType(F->getType(), AnonTy)) - break; - ++Index; - continue; - } - - // If the field looks like this: - // struct { ... } A; - QualType FieldType = F->getType(); - if (const auto *RecType = dyn_cast(FieldType)) { - const RecordDecl *RecDecl = RecType->getDecl(); - if (RecDecl->getDeclContext() == Owner && - !RecDecl->getIdentifier()) { - if (Context.hasSameType(FieldType, AnonTy)) - break; - ++Index; - continue; - } - } - } - - 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; - } - - 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 Index1 = findUntaggedStructOrUnionIndex(D1)) { - if (Optional Index2 = findUntaggedStructOrUnionIndex(D2)) { - if (*Index1 != *Index2) - return false; - } - } - } - - // If both declarations are class template specializations, we know - // the ODR applies, so check the template and template arguments. - ClassTemplateSpecializationDecl *Spec1 - = dyn_cast(D1); - ClassTemplateSpecializationDecl *Spec2 - = dyn_cast(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; - - // 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(D1)) { - if (CXXRecordDecl *D2CXX = dyn_cast(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; -} - -/// \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()); -} - -static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - ClassTemplateDecl *D1, - ClassTemplateDecl *D2) { - // Check template parameters. - if (!IsStructurallyEquivalent(Context, - D1->getTemplateParameters(), - D2->getTemplateParameters())) - return false; - - // Check the templated declaration. - return Context.IsStructurallyEquivalent(D1->getTemplatedDecl(), - D2->getTemplatedDecl()); -} - -/// \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(); - - // Produce a tentative equivalence D1 <-> D2, which will be checked later. - EquivToD1 = D2->getCanonicalDecl(); - Context.DeclsToCheck.push_back(D1->getCanonicalDecl()); - return true; -} - -bool StructuralEquivalenceContext::IsStructurallyEquivalent(Decl *D1, - Decl *D2) { - if (!::IsStructurallyEquivalent(*this, D1, D2)) - return false; - - return !Finish(); -} - -bool StructuralEquivalenceContext::IsStructurallyEquivalent(QualType T1, - QualType T2) { - if (!::IsStructurallyEquivalent(*this, T1, T2)) - return false; - - return !Finish(); -} - -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(D1)) { - if (RecordDecl *Record2 = dyn_cast(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(D1)) { - if (EnumDecl *Enum2 = dyn_cast(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(D1)) { - if (TypedefNameDecl *Typedef2 = dyn_cast(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(D1)) { - if (ClassTemplateDecl *ClassTemplate2 = dyn_cast(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(D1)) { - if (TemplateTypeParmDecl *TTP2 = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (NonTypeTemplateParmDecl *NTTP1 - = dyn_cast(D1)) { - if (NonTypeTemplateParmDecl *NTTP2 - = dyn_cast(D2)) { - if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2)) - Equivalent = false; - } else { - // Kind mismatch. - Equivalent = false; - } - } else if (TemplateTemplateParmDecl *TTP1 - = dyn_cast(D1)) { - if (TemplateTemplateParmDecl *TTP2 - = dyn_cast(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! - } - - return false; -} - //---------------------------------------------------------------------------- // Import Types //---------------------------------------------------------------------------- +using namespace clang; + QualType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); @@ -2634,7 +1251,7 @@ bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), Importer.getNonEquivalentDecls()); - return Ctx.IsStructurallyEquivalent(From, To); + return Ctx.IsStructurallyEquivalent(From, To); } bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, @@ -2813,10 +1430,10 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { FoundTypedef->getUnderlyingType())) return Importer.Imported(D, FoundTypedef); } - + ConflictingDecls.push_back(FoundDecls[I]); } - + if (!ConflictingDecls.empty()) { Name = Importer.HandleNameConflict(Name, DC, IDNS, ConflictingDecls.data(), @@ -2825,7 +1442,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { return nullptr; } } - + // Import the underlying type of this typedef; QualType T = Importer.Import(D->getUnderlyingType()); if (T.isNull()) @@ -2845,12 +1462,12 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { StartL, Loc, Name.getAsIdentifierInfo(), TInfo); - + ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToTypedef); LexicalDC->addDeclInternal(ToTypedef); - + return ToTypedef; } @@ -3024,9 +1641,10 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { 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 Index1 - = findUntaggedStructOrUnionIndex(D)) { - if (Optional Index2 = + if (Optional Index1 = + StructuralEquivalenceContext::findUntaggedStructOrUnionIndex( + D)) { + if (Optional Index2 = StructuralEquivalenceContext:: findUntaggedStructOrUnionIndex(FoundRecord)) { if (*Index1 != *Index2) continue; @@ -3216,7 +1834,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - + if (FunctionDecl *FoundFunction = dyn_cast(FoundDecls[I])) { if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { @@ -3225,14 +1843,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // 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(); @@ -3241,10 +1859,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { << FoundFunction->getType(); } } - + ConflictingDecls.push_back(FoundDecls[I]); } - + if (!ConflictingDecls.empty()) { Name = Importer.HandleNameConflict(Name, DC, IDNS, ConflictingDecls.data(), @@ -3449,12 +2067,12 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { 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) @@ -3514,7 +2132,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { 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); @@ -3638,12 +2256,12 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { if (ToD) return ToD; - // Determine whether we've already imported this ivar + // Determine whether we've already imported this ivar SmallVector FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCIvarDecl *FoundIvar = dyn_cast(FoundDecls[I])) { - if (Importer.IsStructurallyEquivalent(D->getType(), + if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { Importer.Imported(D, FoundIvar); return FoundIvar; @@ -3702,12 +2320,12 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - + if (VarDecl *FoundVar = dyn_cast(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; @@ -3931,12 +2549,12 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { } // 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(); @@ -4542,7 +3160,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { if (ObjCPropertyDecl *FoundProp = dyn_cast(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(); @@ -7597,7 +6215,7 @@ bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType 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); -- cgit v1.2.1