diff options
Diffstat (limited to 'clang/lib/AST/ASTStructuralEquivalence.cpp')
| -rw-r--r-- | clang/lib/AST/ASTStructuralEquivalence.cpp | 150 |
1 files changed, 144 insertions, 6 deletions
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 0813a5204a5e..d80fc3ce7292 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -517,6 +517,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case TemplateName::Template: case TemplateName::QualifiedTemplate: case TemplateName::SubstTemplateTemplateParm: + case TemplateName::UsingTemplate: // It is sufficient to check value of getAsTemplateDecl. break; @@ -932,6 +933,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; + case Type::BTFTagAttributed: + if (!IsStructurallyEquivalent( + Context, cast<BTFTagAttributedType>(T1)->getWrappedType(), + cast<BTFTagAttributedType>(T2)->getWrappedType())) + return false; + break; + case Type::Paren: if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(), cast<ParenType>(T2)->getInnerType())) @@ -1228,16 +1236,17 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(), Int2->getNumBitsExpr())) return false; + break; } } // end switch return true; } -/// Determine structural equivalence of two fields. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - FieldDecl *Field1, FieldDecl *Field2) { - const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext()); + FieldDecl *Field1, FieldDecl *Field2, + QualType Owner2Type) { + const auto *Owner2 = cast<Decl>(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 @@ -1257,7 +1266,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2( Owner2->getLocation(), Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) - << Context.ToCtx.getTypeDeclType(Owner2); + << Owner2Type; Context.Diag2(Field2->getLocation(), diag::note_odr_field_name) << Field2->getDeclName(); Context.Diag1(Field1->getLocation(), diag::note_odr_field_name) @@ -1272,7 +1281,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2( Owner2->getLocation(), Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) - << Context.ToCtx.getTypeDeclType(Owner2); + << Owner2Type; Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); Context.Diag1(Field1->getLocation(), diag::note_odr_field) @@ -1288,6 +1297,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +/// Determine structural equivalence of two fields. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + FieldDecl *Field1, FieldDecl *Field2) { + const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext()); + return IsStructurallyEquivalent(Context, Field1, Field2, + Context.ToCtx.getTypeDeclType(Owner2)); +} + /// Determine structural equivalence of two methods. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, CXXMethodDecl *Method1, @@ -1602,6 +1619,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } // Check the fields for consistency. + QualType D2Type = Context.ToCtx.getTypeDeclType(D2); RecordDecl::field_iterator Field2 = D2->field_begin(), Field2End = D2->field_end(); for (RecordDecl::field_iterator Field1 = D1->field_begin(), @@ -1620,7 +1638,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } - if (!IsStructurallyEquivalent(Context, *Field1, *Field2)) + if (!IsStructurallyEquivalent(Context, *Field1, *Field2, D2Type)) return false; } @@ -1926,6 +1944,126 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ObjCIvarDecl *D1, ObjCIvarDecl *D2, + QualType Owner2Type) { + if (D1->getAccessControl() != D2->getAccessControl()) + return false; + + return IsStructurallyEquivalent(Context, cast<FieldDecl>(D1), + cast<FieldDecl>(D2), Owner2Type); +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ObjCIvarDecl *D1, ObjCIvarDecl *D2) { + QualType Owner2Type = + Context.ToCtx.getObjCInterfaceType(D2->getContainingInterface()); + return IsStructurallyEquivalent(Context, D1, D2, Owner2Type); +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ObjCMethodDecl *Method1, + ObjCMethodDecl *Method2) { + bool PropertiesEqual = + Method1->isInstanceMethod() == Method2->isInstanceMethod() && + Method1->isVariadic() == Method2->isVariadic() && + Method1->isDirectMethod() == Method2->isDirectMethod(); + if (!PropertiesEqual) + return false; + + // Compare selector slot names. + Selector Selector1 = Method1->getSelector(), + Selector2 = Method2->getSelector(); + unsigned NumArgs = Selector1.getNumArgs(); + if (NumArgs != Selector2.getNumArgs()) + return false; + // Compare all selector slots. For selectors with arguments it means all arg + // slots. And if there are no arguments, compare the first-and-only slot. + unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1; + for (unsigned I = 0; I < SlotsToCheck; ++I) { + if (!IsStructurallyEquivalent(Selector1.getIdentifierInfoForSlot(I), + Selector2.getIdentifierInfoForSlot(I))) + return false; + } + + // Compare types. + if (!IsStructurallyEquivalent(Context, Method1->getReturnType(), + Method2->getReturnType())) + return false; + assert( + Method1->param_size() == Method2->param_size() && + "Same number of arguments should be already enforced in Selector checks"); + for (ObjCMethodDecl::param_type_iterator + ParamT1 = Method1->param_type_begin(), + ParamT1End = Method1->param_type_end(), + ParamT2 = Method2->param_type_begin(), + ParamT2End = Method2->param_type_end(); + (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End); + ++ParamT1, ++ParamT2) { + if (!IsStructurallyEquivalent(Context, *ParamT1, *ParamT2)) + return false; + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ObjCCategoryDecl *D1, + ObjCCategoryDecl *D2) { + if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier())) + return false; + + if (!IsStructurallyEquivalent(D1->getClassInterface()->getIdentifier(), + D2->getClassInterface()->getIdentifier())) + return false; + + // Compare protocols. + ObjCCategoryDecl::protocol_iterator Protocol2 = D2->protocol_begin(), + Protocol2End = D2->protocol_end(); + for (ObjCCategoryDecl::protocol_iterator Protocol1 = D1->protocol_begin(), + Protocol1End = D1->protocol_end(); + Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) { + if (Protocol2 == Protocol2End) + return false; + if (!IsStructurallyEquivalent((*Protocol1)->getIdentifier(), + (*Protocol2)->getIdentifier())) + return false; + } + if (Protocol2 != Protocol2End) + return false; + + // Compare ivars. + QualType D2Type = Context.ToCtx.getObjCInterfaceType(D2->getClassInterface()); + ObjCCategoryDecl::ivar_iterator Ivar2 = D2->ivar_begin(), + Ivar2End = D2->ivar_end(); + for (ObjCCategoryDecl::ivar_iterator Ivar1 = D1->ivar_begin(), + Ivar1End = D1->ivar_end(); + Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) { + if (Ivar2 == Ivar2End) + return false; + if (!IsStructurallyEquivalent(Context, *Ivar1, *Ivar2, D2Type)) + return false; + } + if (Ivar2 != Ivar2End) + return false; + + // Compare methods. + ObjCCategoryDecl::method_iterator Method2 = D2->meth_begin(), + Method2End = D2->meth_end(); + for (ObjCCategoryDecl::method_iterator Method1 = D1->meth_begin(), + Method1End = D1->meth_end(); + Method1 != Method1End; ++Method1, ++Method2) { + if (Method2 == Method2End) + return false; + if (!IsStructurallyEquivalent(Context, *Method1, *Method2)) + return false; + } + if (Method2 != Method2End) + return false; + + return true; +} + /// Determine structural equivalence of two declarations. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1, Decl *D2) { |
