diff options
Diffstat (limited to 'lib/AST/ASTImporter.cpp')
-rw-r--r-- | lib/AST/ASTImporter.cpp | 117 |
1 files changed, 50 insertions, 67 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 3879907..3e952ac 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -119,7 +119,8 @@ namespace clang { bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs); - bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord); + bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, + bool Complain = true); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); Decl *VisitDecl(Decl *D); @@ -201,12 +202,16 @@ namespace { /// \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; + StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2, llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls, - bool StrictTypeSpelling = false) + bool StrictTypeSpelling = false, + bool Complain = true) : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls), - StrictTypeSpelling(StrictTypeSpelling) { } + StrictTypeSpelling(StrictTypeSpelling), Complain(Complain) { } /// \brief Determine whether the two declarations are structurally /// equivalent. @@ -223,10 +228,16 @@ namespace { public: DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) { + if (!Complain) + return DiagnosticBuilder::getEmpty(); + return C1.getDiagnostics().Report(Loc, DiagID); } DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) { + if (!Complain) + return DiagnosticBuilder::getEmpty(); + return C2.getDiagnostics().Report(Loc, DiagID); } }; @@ -237,45 +248,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1, Decl *D2); -/// \brief Determine if two APInts have the same value, after zero-extending -/// one of them (if needed!) to ensure that the bit-widths match. -static bool IsSameValue(const llvm::APInt &I1, const llvm::APInt &I2) { - if (I1.getBitWidth() == I2.getBitWidth()) - return I1 == I2; - - if (I1.getBitWidth() > I2.getBitWidth()) - return I1 == I2.zext(I1.getBitWidth()); - - return I1.zext(I2.getBitWidth()) == I2; -} - -/// \brief Determine if two APSInts have the same value, zero- or sign-extending -/// as needed. -static bool IsSameValue(const llvm::APSInt &I1, const llvm::APSInt &I2) { - if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) - return I1 == I2; - - // Check for a bit-width mismatch. - if (I1.getBitWidth() > I2.getBitWidth()) - return IsSameValue(I1, I2.extend(I1.getBitWidth())); - else if (I2.getBitWidth() > I1.getBitWidth()) - return IsSameValue(I1.extend(I2.getBitWidth()), I2); - - // We have a signedness mismatch. Turn the signed value into an unsigned - // value. - if (I1.isSigned()) { - if (I1.isNegative()) - return false; - - return llvm::APSInt(I1, true) == I2; - } - - if (I2.isNegative()) - return false; - - return I1 == llvm::APSInt(I2, true); -} - /// \brief Determine structural equivalence of two expressions. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Expr *E1, Expr *E2) { @@ -322,7 +294,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Arg2.getIntegralType())) return false; - return IsSameValue(*Arg1.getAsIntegral(), *Arg2.getAsIntegral()); + return llvm::APSInt::isSameValue(Arg1.getAsIntegral(), Arg2.getAsIntegral()); case TemplateArgument::Declaration: if (!Arg1.getAsDecl() || !Arg2.getAsDecl()) @@ -467,7 +439,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::ConstantArray: { const ConstantArrayType *Array1 = cast<ConstantArrayType>(T1); const ConstantArrayType *Array2 = cast<ConstantArrayType>(T2); - if (!IsSameValue(Array1->getSize(), Array2->getSize())) + if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize())) return false; if (!IsArrayStructurallyEquivalent(Context, Array1, Array2)) @@ -1002,9 +974,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } // Check the fields for consistency. - CXXRecordDecl::field_iterator Field2 = D2->field_begin(), + RecordDecl::field_iterator Field2 = D2->field_begin(), Field2End = D2->field_end(); - for (CXXRecordDecl::field_iterator Field1 = D1->field_begin(), + for (RecordDecl::field_iterator Field1 = D1->field_begin(), Field1End = D1->field_end(); Field1 != Field1End; ++Field1, ++Field2) { @@ -1053,7 +1025,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, llvm::APSInt Val1 = EC1->getInitVal(); llvm::APSInt Val2 = EC2->getInitVal(); - if (!IsSameValue(Val1, Val2) || + if (!llvm::APSInt::isSameValue(Val1, Val2) || !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) { Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.C2.getTypeDeclType(D2); @@ -1852,19 +1824,14 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.HasPublicFields = FromData.HasPublicFields; ToData.HasMutableFields = FromData.HasMutableFields; ToData.HasOnlyCMembers = FromData.HasOnlyCMembers; + ToData.HasInClassInitializer = FromData.HasInClassInitializer; ToData.HasTrivialDefaultConstructor = FromData.HasTrivialDefaultConstructor; ToData.HasConstexprNonCopyMoveConstructor = FromData.HasConstexprNonCopyMoveConstructor; ToData.DefaultedDefaultConstructorIsConstexpr = FromData.DefaultedDefaultConstructorIsConstexpr; - ToData.DefaultedCopyConstructorIsConstexpr - = FromData.DefaultedCopyConstructorIsConstexpr; - ToData.DefaultedMoveConstructorIsConstexpr - = FromData.DefaultedMoveConstructorIsConstexpr; ToData.HasConstexprDefaultConstructor = FromData.HasConstexprDefaultConstructor; - ToData.HasConstexprCopyConstructor = FromData.HasConstexprCopyConstructor; - ToData.HasConstexprMoveConstructor = FromData.HasConstexprMoveConstructor; ToData.HasTrivialCopyConstructor = FromData.HasTrivialCopyConstructor; ToData.HasTrivialMoveConstructor = FromData.HasTrivialMoveConstructor; ToData.HasTrivialCopyAssignment = FromData.HasTrivialCopyAssignment; @@ -1991,7 +1958,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { QualType ToType = Importer.Import(From.getIntegralType()); if (ToType.isNull()) return TemplateArgument(); - return TemplateArgument(*From.getAsIntegral(), ToType); + return TemplateArgument(From, ToType); } case TemplateArgument::Declaration: @@ -2052,10 +2019,11 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, } bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, - RecordDecl *ToRecord) { + RecordDecl *ToRecord, bool Complain) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls()); + Importer.getNonEquivalentDecls(), + false, Complain); return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord); } @@ -2335,7 +2303,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // We may already have a record of the same name; try to find and match it. RecordDecl *AdoptDecl = 0; - if (!DC->isFunctionOrMethod() && SearchName) { + if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; llvm::SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(SearchName, FoundDecls); @@ -2351,25 +2319,31 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) { if (RecordDecl *FoundDef = FoundRecord->getDefinition()) { - if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) { + if ((SearchName && !D->isCompleteDefinition()) + || (D->isCompleteDefinition() && + D->isAnonymousStructOrUnion() + == FoundDef->isAnonymousStructOrUnion() && + IsStructuralMatch(D, FoundDef))) { // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. // FIXME: For C++, we should also merge methods here. return Importer.Imported(D, FoundDef); } - } else { + } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward // declaration rather than building a new one. AdoptDecl = FoundRecord; continue; - } + } else if (!SearchName) { + continue; + } } ConflictingDecls.push_back(FoundDecls[I]); } - if (!ConflictingDecls.empty()) { + if (!ConflictingDecls.empty() && SearchName) { Name = Importer.HandleNameConflict(Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); @@ -2395,6 +2369,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); + if (D->isAnonymousStructOrUnion()) + D2->setAnonymousStructOrUnion(true); } Importer.Imported(D, D2); @@ -2661,7 +2637,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, BitWidth, D->isMutable(), - D->hasInClassInitializer()); + D->getInClassInitStyle()); ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); if (ToField->hasInClassInitializer()) @@ -2686,11 +2662,16 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { if (IndirectFieldDecl *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { if (Importer.IsStructurallyEquivalent(D->getType(), - FoundField->getType())) { + FoundField->getType(), + Name)) { Importer.Imported(D, FoundField); return FoundField; } - + + // If there are more anonymous fields to check, continue. + if (!Name && I < N-1) + continue; + Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) @@ -4665,12 +4646,14 @@ Decl *ASTImporter::Imported(Decl *From, Decl *To) { return To; } -bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To) { +bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, + bool Complain) { llvm::DenseMap<const Type *, const Type *>::iterator Pos = ImportedTypes.find(From.getTypePtr()); if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To)) return true; - StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls); + StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, + false, Complain); return Ctx.IsStructurallyEquivalent(From, To); } |