From: Douglas Gregor Date: Wed, 22 Apr 2009 22:18:58 +0000 (+0000) Subject: Support locally-declared external declarations in PCH files X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=14c22f20c077cecd68581952a0c227f8c180be03;p=clang Support locally-declared external declarations in PCH files git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69833 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index a2f4dae490..2afcce3388 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -156,7 +156,11 @@ namespace clang { STATISTICS = 9, /// \brief Record code for the array of tentative definitions. - TENTATIVE_DEFINITIONS = 10 + TENTATIVE_DEFINITIONS = 10, + + /// \brief Record code for the array of locally-scoped external + /// declarations. + LOCALLY_SCOPED_EXTERNAL_DECLS = 11 }; /// \brief Record types used within a source manager block. diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 9bb5ca4f0f..72ca6ad569 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -153,6 +153,10 @@ private: /// file. llvm::SmallVector TentativeDefinitions; + /// \brief The set of locally-scoped external declarations stored in + /// the the PCH file. + llvm::SmallVector LocallyScopedExternalDecls; + /// \brief Mapping from switch-case IDs in the PCH file to /// switch-case statements. std::map SwitchCaseStmts; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 28cca4d0ff..66a849d576 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1720,6 +1720,14 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) { } TentativeDefinitions.swap(Record); break; + + case pch::LOCALLY_SCOPED_EXTERNAL_DECLS: + if (!LocallyScopedExternalDecls.empty()) { + Error("Duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file"); + return Failure; + } + LocallyScopedExternalDecls.swap(Record); + break; } } @@ -2537,6 +2545,14 @@ void PCHReader::InitializeSema(Sema &S) { VarDecl *Var = cast(GetDecl(TentativeDefinitions[I])); SemaObj->TentativeDefinitions[Var->getDeclName()] = Var; } + + // If there were any locally-scoped external declarations, + // deserialize them and add them to Sema's table of locally-scoped + // external declarations. + for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) { + NamedDecl *D = cast(GetDecl(LocallyScopedExternalDecls[I])); + SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D; + } } IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) { diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 097ced2363..0aada62599 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -2033,6 +2033,16 @@ void PCHWriter::WritePCH(Sema &SemaRef) { TD != TDEnd; ++TD) AddDeclRef(TD->second, TentativeDefinitions); + // Build a record containing all of the locally-scoped external + // declarations in this header file. Generally, this record will be + // empty. + RecordData LocallyScopedExternalDecls; + for (llvm::DenseMap::iterator + TD = SemaRef.LocallyScopedExternalDecls.begin(), + TDEnd = SemaRef.LocallyScopedExternalDecls.end(); + TD != TDEnd; ++TD) + AddDeclRef(TD->second, LocallyScopedExternalDecls); + // Write the remaining PCH contents. RecordData Record; Stream.EnterSubblock(pch::PCH_BLOCK_ID, 3); @@ -2058,6 +2068,11 @@ void PCHWriter::WritePCH(Sema &SemaRef) { // Write the record containing tentative definitions. if (!TentativeDefinitions.empty()) Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions); + + // Write the record containing locally-scoped external definitions. + if (!LocallyScopedExternalDecls.empty()) + Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS, + LocallyScopedExternalDecls); // Some simple statistics Record.clear(); diff --git a/test/PCH/nonvisible-external-defs.c b/test/PCH/nonvisible-external-defs.c new file mode 100644 index 0000000000..bfe5ccab20 --- /dev/null +++ b/test/PCH/nonvisible-external-defs.c @@ -0,0 +1,10 @@ +// Test this without pch. +// RUN: clang-cc -include %S/nonvisible-external-defs.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/nonvisible-external-defs.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +int g(int, float); // expected-error{{conflicting types}} + +// expected-note{{previous declaration}} diff --git a/test/PCH/nonvisible-external-defs.h b/test/PCH/nonvisible-external-defs.h new file mode 100644 index 0000000000..a36fc2ea46 --- /dev/null +++ b/test/PCH/nonvisible-external-defs.h @@ -0,0 +1,11 @@ +// Helper for PCH test nonvisible-external-defs.h + + + + + + + +void f() { + extern int g(int, int); +}