diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index ecc73c97fca6d2ac3c8ad40402a119012204440c..e0950192e35e0ce0ccaad3a4e0c192d5f28c8c5b 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -290,8 +290,17 @@ private: /// in the chain. DeclUpdateOffsetsMap DeclUpdateOffsets; - typedef llvm::DenseMap > + struct ReplacedDeclInfo { + Module *Mod; + uint64_t Offset; + unsigned RawLoc; + + ReplacedDeclInfo() : Mod(0), Offset(0), RawLoc(0) {} + ReplacedDeclInfo(Module *Mod, uint64_t Offset, unsigned RawLoc) + : Mod(Mod), Offset(Offset), RawLoc(RawLoc) {} + }; + + typedef llvm::DenseMap DeclReplacementMap; /// \brief Declarations that have been replaced in a later file in the chain. DeclReplacementMap ReplacedDecls; diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index bad5c379bcbf738fb34366002844d94addcdbe6b..8c0ea4fc33c22406c1dd7412e540fbc4c01294e4 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -286,14 +286,24 @@ private: /// another module. SmallVector LocalChainedObjCCategories; + struct ReplacedDeclInfo { + serialization::DeclID ID; + uint64_t Offset; + unsigned Loc; + + ReplacedDeclInfo() : ID(0), Offset(0), Loc(0) {} + ReplacedDeclInfo(serialization::DeclID ID, uint64_t Offset, + SourceLocation Loc) + : ID(ID), Offset(Offset), Loc(Loc.getRawEncoding()) {} + }; + /// \brief Decls that have been replaced in the current dependent AST file. /// /// When a decl changes fundamentally after being deserialized (this shouldn't /// happen, but the ObjC AST nodes are designed this way), it will be /// serialized again. In this case, it is registered here, so that the reader /// knows to read the updated version. - SmallVector, 16> - ReplacedDecls; + SmallVector ReplacedDecls; /// \brief Statements that we've encountered while serializing a /// declaration or type. diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 7ae0c4206991a8bd724bddfcfcd0376447bc5bf2..4554f05256005a21c041de41515306f0cb2cf87f 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2217,13 +2217,13 @@ ASTReader::ReadASTBlock(Module &F) { } case DECL_REPLACEMENTS: { - if (Record.size() % 2 != 0) { + if (Record.size() % 3 != 0) { Error("invalid DECL_REPLACEMENTS block in AST file"); return Failure; } - for (unsigned I = 0, N = Record.size(); I != N; I += 2) + for (unsigned I = 0, N = Record.size(); I != N; I += 3) ReplacedDecls[getGlobalDeclID(F, Record[I])] - = std::make_pair(&F, Record[I+1]); + = ReplacedDeclInfo(&F, Record[I+1], Record[I+2]); break; } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 7b37bbfa1b696aedb18a1f72fcb4ce02555f47ca..d414c07290799445ad842dce0ec7c888ed5604bb 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1449,8 +1449,10 @@ ASTReader::RecordLocation ASTReader::DeclCursorForID(DeclID ID, unsigned &RawLocation) { // See if there's an override. DeclReplacementMap::iterator It = ReplacedDecls.find(ID); - if (It != ReplacedDecls.end()) - return RecordLocation(It->second.first, It->second.second); + if (It != ReplacedDecls.end()) { + RawLocation = It->second.RawLoc; + return RecordLocation(It->second.Mod, It->second.Offset); + } GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 1b44baa9ce5382ed3d1204cd483a0a65834a1995..9716447dfa93aae4229a9ae790c98b9a777db0c6 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3234,10 +3234,11 @@ void ASTWriter::WriteDeclReplacementsBlock() { return; RecordData Record; - for (SmallVector, 16>::iterator + for (SmallVector::iterator I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) { - Record.push_back(I->first); - Record.push_back(I->second); + Record.push_back(I->ID); + Record.push_back(I->Offset); + Record.push_back(I->Loc); } Stream.EmitRecord(DECL_REPLACEMENTS, Record); } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 3e3e28dfbb7d02271de56df53458398e94d21a17..c35d4b0d220651883edf4a0e1f52ec1d5d3b61b3 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1647,7 +1647,8 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { if (ID < FirstDeclID) { // We're replacing a decl in a previous file. - ReplacedDecls.push_back(std::make_pair(ID, Stream.GetCurrentBitNo())); + ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(), + D->getLocation())); } else { unsigned Index = ID - FirstDeclID; diff --git a/clang/test/PCH/replaced-decl.m b/clang/test/PCH/replaced-decl.m new file mode 100644 index 0000000000000000000000000000000000000000..b9fee950d7a140b48d47f824b02444a28557c15a --- /dev/null +++ b/clang/test/PCH/replaced-decl.m @@ -0,0 +1,22 @@ +// Without PCH +// RUN: %clang_cc1 -fsyntax-only -verify %s -include %s -include %s + +// With PCH +// RUN: %clang_cc1 -fsyntax-only -verify %s -chain-include %s -chain-include %s + +#ifndef HEADER1 +#define HEADER1 + +@class I; + +#elif !defined(HEADER2) +#define HEADER2 + +@interface I // expected-note {{previous}} +@end + +#else + +typedef int I; // expected-error {{redefinition}} + +#endif