diff options
Diffstat (limited to 'lib/AST/ASTImporter.cpp')
-rw-r--r-- | lib/AST/ASTImporter.cpp | 163 |
1 files changed, 100 insertions, 63 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 0d4f303..d2e6d29 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// #include "clang/AST/ASTImporter.h" - #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/DeclCXX.h" @@ -122,6 +121,7 @@ namespace clang { bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain = true); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); + bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); @@ -206,12 +206,16 @@ namespace { /// \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) { } + StrictTypeSpelling(StrictTypeSpelling), Complain(Complain), + LastDiagFromC2(false) {} /// \brief Determine whether the two declarations are structurally /// equivalent. @@ -229,11 +233,17 @@ namespace { 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); } }; @@ -892,14 +902,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &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 llvm::Optional<unsigned> -findAnonymousStructOrUnionIndex(RecordDecl *Anon) { +static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) { ASTContext &Context = Anon->getASTContext(); QualType AnonTy = Context.getRecordType(Anon); RecordDecl *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext()); if (!Owner) - return llvm::Optional<unsigned>(); + return None; unsigned Index = 0; for (DeclContext::decl_iterator D = Owner->noload_decls_begin(), @@ -934,10 +943,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, 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 (llvm::Optional<unsigned> Index1 - = findAnonymousStructOrUnionIndex(D1)) { - if (llvm::Optional<unsigned> Index2 - = findAnonymousStructOrUnionIndex(D2)) { + if (Optional<unsigned> Index1 = findAnonymousStructOrUnionIndex(D1)) { + if (Optional<unsigned> Index2 = findAnonymousStructOrUnionIndex(D2)) { if (*Index1 != *Index2) return false; } @@ -1612,8 +1619,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ToEPI.ExceptionSpecTemplate = cast_or_null<FunctionDecl>( Importer.Import(FromEPI.ExceptionSpecTemplate)); - return Importer.getToContext().getFunctionType(ToResultType, ArgTypes.data(), - ArgTypes.size(), ToEPI); + return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI); } QualType ASTNodeImporter::VisitParenType(const ParenType *T) { @@ -1825,7 +1831,7 @@ void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) { if (RecordDecl *ToRecord = cast_or_null<RecordDecl>(ToD)) { - if (FromRecord->getDefinition() && !ToRecord->getDefinition()) { + if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && !ToRecord->getDefinition()) { ImportDefinition(FromRecord, ToRecord); } } @@ -1907,11 +1913,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data(); struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data(); ToData.UserDeclaredConstructor = FromData.UserDeclaredConstructor; - ToData.UserDeclaredCopyConstructor = FromData.UserDeclaredCopyConstructor; - ToData.UserDeclaredMoveConstructor = FromData.UserDeclaredMoveConstructor; - ToData.UserDeclaredCopyAssignment = FromData.UserDeclaredCopyAssignment; - ToData.UserDeclaredMoveAssignment = FromData.UserDeclaredMoveAssignment; - ToData.UserDeclaredDestructor = FromData.UserDeclaredDestructor; + ToData.UserDeclaredSpecialMembers = FromData.UserDeclaredSpecialMembers; ToData.Aggregate = FromData.Aggregate; ToData.PlainOldData = FromData.PlainOldData; ToData.Empty = FromData.Empty; @@ -1925,30 +1927,41 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.HasMutableFields = FromData.HasMutableFields; ToData.HasOnlyCMembers = FromData.HasOnlyCMembers; ToData.HasInClassInitializer = FromData.HasInClassInitializer; - ToData.HasTrivialDefaultConstructor = FromData.HasTrivialDefaultConstructor; + ToData.HasUninitializedReferenceMember + = FromData.HasUninitializedReferenceMember; + ToData.NeedOverloadResolutionForMoveConstructor + = FromData.NeedOverloadResolutionForMoveConstructor; + ToData.NeedOverloadResolutionForMoveAssignment + = FromData.NeedOverloadResolutionForMoveAssignment; + ToData.NeedOverloadResolutionForDestructor + = FromData.NeedOverloadResolutionForDestructor; + ToData.DefaultedMoveConstructorIsDeleted + = FromData.DefaultedMoveConstructorIsDeleted; + ToData.DefaultedMoveAssignmentIsDeleted + = FromData.DefaultedMoveAssignmentIsDeleted; + ToData.DefaultedDestructorIsDeleted = FromData.DefaultedDestructorIsDeleted; + ToData.HasTrivialSpecialMembers = FromData.HasTrivialSpecialMembers; + ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor; ToData.HasConstexprNonCopyMoveConstructor = FromData.HasConstexprNonCopyMoveConstructor; ToData.DefaultedDefaultConstructorIsConstexpr = FromData.DefaultedDefaultConstructorIsConstexpr; ToData.HasConstexprDefaultConstructor = FromData.HasConstexprDefaultConstructor; - ToData.HasTrivialCopyConstructor = FromData.HasTrivialCopyConstructor; - ToData.HasTrivialMoveConstructor = FromData.HasTrivialMoveConstructor; - ToData.HasTrivialCopyAssignment = FromData.HasTrivialCopyAssignment; - ToData.HasTrivialMoveAssignment = FromData.HasTrivialMoveAssignment; - ToData.HasTrivialDestructor = FromData.HasTrivialDestructor; - ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor; ToData.HasNonLiteralTypeFieldsOrBases = FromData.HasNonLiteralTypeFieldsOrBases; // ComputedVisibleConversions not imported. ToData.UserProvidedDefaultConstructor = FromData.UserProvidedDefaultConstructor; - ToData.DeclaredDefaultConstructor = FromData.DeclaredDefaultConstructor; - ToData.DeclaredCopyConstructor = FromData.DeclaredCopyConstructor; - ToData.DeclaredMoveConstructor = FromData.DeclaredMoveConstructor; - ToData.DeclaredCopyAssignment = FromData.DeclaredCopyAssignment; - ToData.DeclaredMoveAssignment = FromData.DeclaredMoveAssignment; - ToData.DeclaredDestructor = FromData.DeclaredDestructor; + ToData.DeclaredSpecialMembers = FromData.DeclaredSpecialMembers; + ToData.ImplicitCopyConstructorHasConstParam + = FromData.ImplicitCopyConstructorHasConstParam; + ToData.ImplicitCopyAssignmentHasConstParam + = FromData.ImplicitCopyAssignmentHasConstParam; + ToData.HasDeclaredCopyConstructorWithConstParam + = FromData.HasDeclaredCopyConstructorWithConstParam; + ToData.HasDeclaredCopyAssignmentWithConstParam + = FromData.HasDeclaredCopyAssignmentWithConstParam; ToData.FailedImplicitMoveConstructor = FromData.FailedImplicitMoveConstructor; ToData.FailedImplicitMoveAssignment = FromData.FailedImplicitMoveAssignment; @@ -2143,7 +2156,18 @@ bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum); } -bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, +bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, + EnumConstantDecl *ToEC) +{ + const llvm::APSInt &FromVal = FromEC->getInitVal(); + const llvm::APSInt &ToVal = ToEC->getInitVal(); + + return FromVal.isSigned() == ToVal.isSigned() && + FromVal.getBitWidth() == ToVal.getBitWidth() && + FromVal == ToVal; +} + +bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), @@ -2185,7 +2209,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace(); } else { SmallVector<NamedDecl *, 4> ConflictingDecls; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace)) @@ -2248,7 +2272,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -2328,7 +2352,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // We may already have an enum of the same name; try to find and match it. if (!DC->isFunctionOrMethod() && SearchName) { SmallVector<NamedDecl *, 4> ConflictingDecls; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(SearchName, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -2414,7 +2438,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { RecordDecl *AdoptDecl = 0; if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(SearchName, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -2431,10 +2455,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 (llvm::Optional<unsigned> Index1 + if (Optional<unsigned> Index1 = findAnonymousStructOrUnionIndex(D)) { - if (llvm::Optional<unsigned> Index2 - = findAnonymousStructOrUnionIndex(FoundRecord)) { + if (Optional<unsigned> Index2 = + findAnonymousStructOrUnionIndex(FoundRecord)) { if (*Index1 != *Index2) continue; } @@ -2521,12 +2545,18 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - + + if (EnumConstantDecl *FoundEnumConstant + = dyn_cast<EnumConstantDecl>(FoundDecls[I])) { + if (IsStructuralMatch(D, FoundEnumConstant)) + return Importer.Imported(D, FoundEnumConstant); + } + ConflictingDecls.push_back(FoundDecls[I]); } @@ -2567,7 +2597,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -2629,8 +2659,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { FunctionProtoType::ExtProtoInfo DefaultEPI; FromTy = Importer.getFromContext().getFunctionType( FromFPT->getResultType(), - FromFPT->arg_type_begin(), - FromFPT->arg_type_end() - FromFPT->arg_type_begin(), + ArrayRef<QualType>(FromFPT->arg_type_begin(), + FromFPT->getNumArgs()), DefaultEPI); usedDifferentExceptionSpec = true; } @@ -2686,8 +2716,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { cast<CXXRecordDecl>(DC), D->getInnerLocStart(), NameInfo, T, TInfo, - Method->isStatic(), - Method->getStorageClassAsWritten(), + Method->getStorageClass(), Method->isInlineSpecified(), D->isConstexpr(), Importer.Import(D->getLocEnd())); @@ -2695,7 +2724,6 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, D->getInnerLocStart(), NameInfo, T, TInfo, D->getStorageClass(), - D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->isConstexpr()); @@ -2777,7 +2805,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { return 0; // Determine whether we've already imported this field. - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) { @@ -2833,7 +2861,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { return 0; // Determine whether we've already imported this field. - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (IndirectFieldDecl *FoundField @@ -2898,7 +2926,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { return 0; // Determine whether we've already imported this ivar - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) { @@ -2953,7 +2981,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { VarDecl *MergeWithVar = 0; SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -3046,8 +3074,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, - D->getStorageClass(), - D->getStorageClassAsWritten()); + D->getStorageClass()); ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); @@ -3115,7 +3142,6 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), - D->getStorageClassAsWritten(), /*FIXME: Default argument*/ 0); ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); return Importer.Imported(D, ToParm); @@ -3129,7 +3155,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) return 0; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecls[I])) { @@ -3376,7 +3402,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { return 0; ObjCProtocolDecl *MergeWithProtocol = 0; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) @@ -3480,10 +3506,13 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, // Import categories. When the categories themselves are imported, they'll // hook themselves into this interface. - for (ObjCCategoryDecl *FromCat = From->getCategoryList(); FromCat; - FromCat = FromCat->getNextClassCategory()) - Importer.Import(FromCat); - + for (ObjCInterfaceDecl::known_categories_iterator + Cat = From->known_categories_begin(), + CatEnd = From->known_categories_end(); + Cat != CatEnd; ++Cat) { + Importer.Import(*Cat); + } + // If we have an @implementation, import it as well. if (From->getImplementation()) { ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>( @@ -3523,7 +3552,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Look for an existing interface with the same name. ObjCInterfaceDecl *MergeWithIface = 0; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + 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)) @@ -3675,7 +3704,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { return 0; // Check whether we have already imported this property. - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCPropertyDecl *FoundProp @@ -3908,7 +3937,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + 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)) @@ -4295,7 +4324,7 @@ ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, bool MinimalImport) : ToContext(ToContext), FromContext(FromContext), ToFileManager(ToFileManager), FromFileManager(FromFileManager), - Minimal(MinimalImport) + Minimal(MinimalImport), LastDiagFromFrom(false) { ImportedDecls[FromContext.getTranslationUnitDecl()] = ToContext.getTranslationUnitDecl(); @@ -4798,10 +4827,18 @@ DeclarationName ASTImporter::HandleNameConflict(DeclarationName Name, } DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) { + if (LastDiagFromFrom) + ToContext.getDiagnostics().notePriorDiagnosticFrom( + FromContext.getDiagnostics()); + LastDiagFromFrom = false; return ToContext.getDiagnostics().Report(Loc, DiagID); } DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) { + if (!LastDiagFromFrom) + FromContext.getDiagnostics().notePriorDiagnosticFrom( + ToContext.getDiagnostics()); + LastDiagFromFrom = true; return FromContext.getDiagnostics().Report(Loc, DiagID); } |