diff options
Diffstat (limited to 'lib/AST/ASTStructuralEquivalence.cpp')
-rw-r--r-- | lib/AST/ASTStructuralEquivalence.cpp | 205 |
1 files changed, 145 insertions, 60 deletions
diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index d19b89bb95..71bbd82481 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -1,9 +1,8 @@ //===- ASTStructuralEquivalence.cpp ---------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -297,6 +296,32 @@ static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +/// Determine structural equivalence based on the ExtInfo of functions. This +/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling +/// conventions bits but must not compare some other bits. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + FunctionType::ExtInfo EI1, + FunctionType::ExtInfo EI2) { + // Compatible functions must have compatible calling conventions. + if (EI1.getCC() != EI2.getCC()) + return false; + + // Regparm is part of the calling convention. + if (EI1.getHasRegParm() != EI2.getHasRegParm()) + return false; + if (EI1.getRegParm() != EI2.getRegParm()) + return false; + + if (EI1.getProducesResult() != EI2.getProducesResult()) + return false; + if (EI1.getNoCallerSavedRegs() != EI2.getNoCallerSavedRegs()) + return false; + if (EI1.getNoCfCheck() != EI2.getNoCfCheck()) + return false; + + return true; +} + /// Determine structural equivalence of two types. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, QualType T1, QualType T2) { @@ -503,7 +528,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Proto1->isVariadic() != Proto2->isVariadic()) return false; - if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) + if (Proto1->getMethodQuals() != Proto2->getMethodQuals()) return false; // Check exceptions, this information is lost in canonical type. @@ -540,7 +565,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, Function1->getReturnType(), Function2->getReturnType())) return false; - if (Function1->getExtInfo() != Function2->getExtInfo()) + if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(), + Function2->getExtInfo())) return false; break; } @@ -834,10 +860,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, IdentifierInfo *Name2 = Field2->getIdentifier(); if (!::IsStructurallyEquivalent(Name1, Name2)) { if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2( + Owner2->getLocation(), + Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(Owner2); Context.Diag2(Field2->getLocation(), diag::note_odr_field_name) << Field2->getDeclName(); @@ -850,10 +875,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, Field1->getType(), Field2->getType())) { if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2( + Owner2->getLocation(), + Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(Owner2); Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); @@ -865,10 +889,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Field1->isBitField() != Field2->isBitField()) { if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2( + Owner2->getLocation(), + Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(Owner2); if (Field1->isBitField()) { Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) @@ -895,9 +918,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Bits1 != Bits2) { if (Context.Complain) { Context.Diag2(Owner2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(Owner2); Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) << Field2->getDeclName() << Field2->getType() << Bits2; @@ -966,10 +988,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { if (D1->isUnion() != D2->isUnion()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here) << D1->getDeclName() << (unsigned)D1->getTagKind(); @@ -1046,7 +1066,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (D1CXX->getNumBases() != D2CXX->getNumBases()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases) << D2CXX->getNumBases(); @@ -1065,7 +1087,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Base2->getType())) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base) << Base2->getType() << Base2->getSourceRange(); @@ -1079,7 +1102,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Base1->isVirtual() != Base2->isVirtual()) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base) << Base2->isVirtual() << Base2->getSourceRange(); @@ -1092,15 +1116,16 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // Check the friends for consistency. CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(), - Friend2End = D2CXX->friend_end(); + Friend2End = D2CXX->friend_end(); for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(), - Friend1End = D1CXX->friend_end(); + Friend1End = D1CXX->friend_end(); Friend1 != Friend1End; ++Friend1, ++Friend2) { if (Friend2 == Friend2End) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - diag::warn_odr_tag_type_inconsistent) - << Context.ToCtx.getTypeDeclType(D2CXX); + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2CXX); Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend); Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend); } @@ -1109,8 +1134,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, *Friend1, *Friend2)) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.ToCtx.getTypeDeclType(D2CXX); + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2CXX); Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend); Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend); } @@ -1120,8 +1147,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Friend2 != Friend2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.ToCtx.getTypeDeclType(D2); + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2); Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend); Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend); } @@ -1129,7 +1158,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } } else if (D1CXX->getNumBases() > 0) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); const CXXBaseSpecifier *Base1 = D1CXX->bases_begin(); Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base) @@ -1149,9 +1180,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Field2 == Field2End) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(Field1->getLocation(), diag::note_odr_field) << Field1->getDeclName() << Field1->getType(); @@ -1166,10 +1196,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Field2 != Field2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); @@ -1200,9 +1228,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (EC2 == EC2End) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator) << EC1->getDeclName() << EC1->getInitVal().toString(10); @@ -1217,9 +1244,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) << EC2->getDeclName() << EC2->getInitVal().toString(10); @@ -1232,10 +1258,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (EC2 != EC2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) << EC2->getDeclName() << EC2->getInitVal().toString(10); @@ -1253,7 +1277,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Params1->size() != Params2->size()) { if (Context.Complain) { Context.Diag2(Params2->getTemplateLoc(), - diag::err_odr_different_num_template_parameters) + Context.getApplicableDiagnostic( + diag::err_odr_different_num_template_parameters)) << Params1->size() << Params2->size(); Context.Diag1(Params1->getTemplateLoc(), diag::note_odr_template_parameter_list); @@ -1265,7 +1290,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, 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.getApplicableDiagnostic( + diag::err_odr_different_template_parameter_kind)); Context.Diag1(Params1->getParam(I)->getLocation(), diag::note_odr_template_parameter_here); } @@ -1285,7 +1311,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, TemplateTypeParmDecl *D2) { if (D1->isParameterPack() != D2->isParameterPack()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_parameter_pack_non_pack)) << D2->isParameterPack(); Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) << D1->isParameterPack(); @@ -1301,7 +1329,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, NonTypeTemplateParmDecl *D2) { if (D1->isParameterPack() != D2->isParameterPack()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_parameter_pack_non_pack)) << D2->isParameterPack(); Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) << D1->isParameterPack(); @@ -1313,7 +1343,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - diag::err_odr_non_type_parameter_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_non_type_parameter_type_inconsistent)) << D2->getType() << D1->getType(); Context.Diag1(D1->getLocation(), diag::note_odr_value_here) << D1->getType(); @@ -1329,7 +1360,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, TemplateTemplateParmDecl *D2) { if (D1->isParameterPack() != D2->isParameterPack()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_parameter_pack_non_pack)) << D2->isParameterPack(); Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) << D1->isParameterPack(); @@ -1485,6 +1518,52 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) { return Index; } +unsigned StructuralEquivalenceContext::getApplicableDiagnostic( + unsigned ErrorDiagnostic) { + if (ErrorOnTagTypeMismatch) + return ErrorDiagnostic; + + switch (ErrorDiagnostic) { + case diag::err_odr_variable_type_inconsistent: + return diag::warn_odr_variable_type_inconsistent; + case diag::err_odr_variable_multiple_def: + return diag::warn_odr_variable_multiple_def; + case diag::err_odr_function_type_inconsistent: + return diag::warn_odr_function_type_inconsistent; + case diag::err_odr_tag_type_inconsistent: + return diag::warn_odr_tag_type_inconsistent; + case diag::err_odr_field_type_inconsistent: + return diag::warn_odr_field_type_inconsistent; + case diag::err_odr_ivar_type_inconsistent: + return diag::warn_odr_ivar_type_inconsistent; + case diag::err_odr_objc_superclass_inconsistent: + return diag::warn_odr_objc_superclass_inconsistent; + case diag::err_odr_objc_method_result_type_inconsistent: + return diag::warn_odr_objc_method_result_type_inconsistent; + case diag::err_odr_objc_method_num_params_inconsistent: + return diag::warn_odr_objc_method_num_params_inconsistent; + case diag::err_odr_objc_method_param_type_inconsistent: + return diag::warn_odr_objc_method_param_type_inconsistent; + case diag::err_odr_objc_method_variadic_inconsistent: + return diag::warn_odr_objc_method_variadic_inconsistent; + case diag::err_odr_objc_property_type_inconsistent: + return diag::warn_odr_objc_property_type_inconsistent; + case diag::err_odr_objc_property_impl_kind_inconsistent: + return diag::warn_odr_objc_property_impl_kind_inconsistent; + case diag::err_odr_objc_synthesize_ivar_inconsistent: + return diag::warn_odr_objc_synthesize_ivar_inconsistent; + case diag::err_odr_different_num_template_parameters: + return diag::warn_odr_different_num_template_parameters; + case diag::err_odr_different_template_parameter_kind: + return diag::warn_odr_different_template_parameter_kind; + case diag::err_odr_parameter_pack_non_pack: + return diag::warn_odr_parameter_pack_non_pack; + case diag::err_odr_non_type_parameter_type_inconsistent: + return diag::warn_odr_non_type_parameter_type_inconsistent; + } + llvm_unreachable("Diagnostic kind not handled in preceding switch"); +} + bool StructuralEquivalenceContext::IsEquivalent(Decl *D1, Decl *D2) { // Ensure that the implementation functions (all static functions in this TU) @@ -1624,6 +1703,12 @@ bool StructuralEquivalenceContext::CheckKindSpecificEquivalence( } } else if (FunctionDecl *FD1 = dyn_cast<FunctionDecl>(D1)) { if (FunctionDecl *FD2 = dyn_cast<FunctionDecl>(D2)) { + if (FD1->isOverloadedOperator()) { + if (!FD2->isOverloadedOperator()) + return false; + if (FD1->getOverloadedOperator() != FD2->getOverloadedOperator()) + return false; + } if (!::IsStructurallyEquivalent(FD1->getIdentifier(), FD2->getIdentifier())) return false; |