From: Douglas Gregor Date: Thu, 10 Feb 2011 18:20:09 +0000 (+0000) Subject: When we're writing macro definitions to an AST/PCH File, sort the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9c7361006b8cd95333958150dd0c803261807b68;p=clang When we're writing macro definitions to an AST/PCH File, sort the macro definitions by macro name first. That way, we'll get a stable ordering in the AST/PCH file. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125297 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index e4fe99cde3..b6789687d7 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1498,6 +1498,14 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Preprocessor Serialization //===----------------------------------------------------------------------===// +static int compareMacroDefinitions(const void *XPtr, const void *YPtr) { + const std::pair &X = + *(const std::pair*)XPtr; + const std::pair &Y = + *(const std::pair*)YPtr; + return X.first->getName().compare(Y.first->getName()); +} + /// \brief Writes the block containing the serialized form of the /// preprocessor. /// @@ -1524,12 +1532,24 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { // emitting each to the PP section. PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); - // FIXME: If we are chaining, don't visit all of the macros! + // Construct the list of macro definitions that need to be serialized. + llvm::SmallVector, 2> + MacrosToEmit; + llvm::SmallPtrSet MacroDefinitionsSeen; for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); I != E; ++I) { - // FIXME: This emits macros in hash table order, we should do it in a stable - // order so that output is reproducible. - MacroInfo *MI = I->second; + MacroDefinitionsSeen.insert(I->first); + MacrosToEmit.push_back(std::make_pair(I->first, I->second)); + } + + // Sort the set of macro definitions that need to be serialized by the + // name of the macro, to provide a stable ordering. + llvm::array_pod_sort(MacrosToEmit.begin(), MacrosToEmit.end(), + &compareMacroDefinitions); + + for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) { + const IdentifierInfo *Name = MacrosToEmit[I].first; + MacroInfo *MI = MacrosToEmit[I].second; // Don't emit builtin macros like __LINE__ to the AST file unless they have // been redefined by the header (in which case they are not isBuiltinMacro). @@ -1540,11 +1560,11 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { // chained PCH, by storing the offset into the original PCH rather than // writing the macro definition a second time. if (MI->isBuiltinMacro() || - (Chain && I->first->isFromAST() && MI->isFromAST())) + (Chain && Name->isFromAST() && MI->isFromAST())) continue; - AddIdentifierRef(I->first, Record); - MacroOffsets[I->first] = Stream.GetCurrentBitNo(); + AddIdentifierRef(Name, Record); + MacroOffsets[Name] = Stream.GetCurrentBitNo(); Record.push_back(MI->getDefinitionLoc().getRawEncoding()); Record.push_back(MI->isUsed()); diff --git a/test/PCH/reinclude.cpp b/test/PCH/reinclude.cpp index 6ab10027c9..71f90282ba 100644 --- a/test/PCH/reinclude.cpp +++ b/test/PCH/reinclude.cpp @@ -4,5 +4,7 @@ // RUN: %clang_cc1 -x c++-header %S/reinclude1.h -emit-pch -o %t1 // RUN: %clang_cc1 -x c++-header %S/reinclude2.h -include-pch %t1 -emit-pch -o %t2 // RUN: %clang_cc1 %s -include-pch %t2 -fsyntax-only -verify +// RUN: %clang_cc1 -x c++-header %S/reinclude2.h -include-pch %t1 -emit-pch -o %t2 -chained-pch +// RUN: %clang_cc1 %s -include-pch %t2 -fsyntax-only -verify int q2 = A::y;