[cfe-commits] r74847 - in /cfe/trunk: include/clang/Frontend/PCHReader.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHReaderDecl.cpp test/PCH/pr4489.c
Douglas Gregor
dgregor at apple.com
Mon Jul 6 11:55:02 PDT 2009
Author: dgregor
Date: Mon Jul 6 13:54:52 2009
New Revision: 74847
URL: http://llvm.org/viewvc/llvm-project?rev=74847&view=rev
Log:
Fix PR 4489, a crash in PCH loading that occurs when loading the name
of a top-level declaration loads another top-level declaration of the
same name whose type depends on the first declaration having been
completed. This commit breaks the circular dependency by delaying
loads of top-level declarations triggered by loading a name until we
are no longer recursively loading types or declarations.
Modified:
cfe/trunk/include/clang/Frontend/PCHReader.h
cfe/trunk/lib/Frontend/PCHReader.cpp
cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
cfe/trunk/test/PCH/pr4489.c
Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=74847&r1=74846&r2=74847&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Mon Jul 6 13:54:52 2009
@@ -30,6 +30,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/DataTypes.h"
+#include <deque>
#include <map>
#include <string>
#include <utility>
@@ -361,7 +362,41 @@
/// Number of visible decl contexts read/total.
unsigned NumVisibleDeclContextsRead, TotalVisibleDeclContexts;
-
+
+ /// \brief When a type or declaration is being loaded from the PCH file, an
+ /// instantance of this RAII object will be available on the stack to
+ /// indicate when we are in a recursive-loading situation.
+ class LoadingTypeOrDecl {
+ PCHReader &Reader;
+ LoadingTypeOrDecl *Parent;
+
+ LoadingTypeOrDecl(const LoadingTypeOrDecl&); // do not implement
+ LoadingTypeOrDecl &operator=(const LoadingTypeOrDecl&); // do not implement
+
+ public:
+ explicit LoadingTypeOrDecl(PCHReader &Reader);
+ ~LoadingTypeOrDecl();
+ };
+ friend class LoadingTypeOrDecl;
+
+ /// \brief If we are currently loading a type or declaration, points to the
+ /// most recent LoadingTypeOrDecl object on the stack.
+ LoadingTypeOrDecl *CurrentlyLoadingTypeOrDecl;
+
+ /// \brief An IdentifierInfo that has been loaded but whose top-level
+ /// declarations of the same name have not (yet) been loaded.
+ struct PendingIdentifierInfo {
+ IdentifierInfo *II;
+ llvm::SmallVector<uint32_t, 4> DeclIDs;
+ };
+
+ /// \brief The set of identifiers that were read while the PCH reader was
+ /// (recursively) loading declarations.
+ ///
+ /// The declarations on the identifier chain for these identifiers will be
+ /// loaded once the recursive loading has completed.
+ std::deque<PendingIdentifierInfo> PendingIdentifierInfos;
+
/// \brief FIXME: document!
llvm::SmallVector<uint64_t, 4> SpecialTypes;
@@ -555,7 +590,10 @@
ReadMethodPool(Selector Sel);
void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
-
+ void SetGloballyVisibleDecls(IdentifierInfo *II,
+ const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
+ bool Nonrecursive = false);
+
/// \brief Report a diagnostic.
DiagnosticBuilder Diag(unsigned DiagID);
Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=74847&r1=74846&r2=74847&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Mon Jul 6 13:54:52 2009
@@ -361,7 +361,8 @@
TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
NumSLocEntriesRead(0), NumStatementsRead(0),
NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
- NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
+ NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
+ CurrentlyLoadingTypeOrDecl(0) { }
PCHReader::~PCHReader() {}
@@ -594,26 +595,14 @@
// Read all of the declarations visible at global scope with this
// name.
- Sema *SemaObj = Reader.getSema();
if (Reader.getContext() == 0) return II;
-
- while (DataLen > 0) {
- NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
- if (SemaObj) {
- // Introduce this declaration into the translation-unit scope
- // and add it to the declaration chain for this identifier, so
- // that (unqualified) name lookup will find it.
- SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
- SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
- } else {
- // Queue this declaration so that it will be added to the
- // translation unit scope and identifier's declaration chain
- // once a Sema object is known.
- Reader.PreloadedDecls.push_back(D);
- }
-
- DataLen -= 4;
+ if (DataLen > 0) {
+ llvm::SmallVector<uint32_t, 4> DeclIDs;
+ for (; DataLen > 0; DataLen -= 4)
+ DeclIDs.push_back(ReadUnalignedLE32(d));
+ Reader.SetGloballyVisibleDecls(II, DeclIDs);
}
+
return II;
}
};
@@ -625,7 +614,6 @@
typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
PCHIdentifierLookupTable;
-// FIXME: use the diagnostics machinery
bool PCHReader::Error(const char *Msg) {
unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
Diag(DiagID);
@@ -1686,6 +1674,9 @@
// after reading this type.
SavedStreamPosition SavedPosition(Stream);
+ // Note that we are loading a type record.
+ LoadingTypeOrDecl Loading(*this);
+
Stream.JumpToBit(Offset);
RecordData Record;
unsigned Code = Stream.ReadCode();
@@ -2220,6 +2211,52 @@
IdentifiersLoaded[ID - 1] = II;
}
+/// \brief Set the globally-visible declarations associated with the given
+/// identifier.
+///
+/// If the PCH reader is currently in a state where the given declaration IDs
+/// cannot safely be resolved, they are queued until it is safe to resolve
+/// them.
+///
+/// \param II an IdentifierInfo that refers to one or more globally-visible
+/// declarations.
+///
+/// \param DeclIDs the set of declaration IDs with the name @p II that are
+/// visible at global scope.
+///
+/// \param Nonrecursive should be true to indicate that the caller knows that
+/// this call is non-recursive, and therefore the globally-visible declarations
+/// will not be placed onto the pending queue.
+void
+PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
+ const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
+ bool Nonrecursive) {
+ if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) {
+ PendingIdentifierInfos.push_back(PendingIdentifierInfo());
+ PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
+ PII.II = II;
+ for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I)
+ PII.DeclIDs.push_back(DeclIDs[I]);
+ return;
+ }
+
+ for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
+ NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
+ if (SemaObj) {
+ // Introduce this declaration into the translation-unit scope
+ // and add it to the declaration chain for this identifier, so
+ // that (unqualified) name lookup will find it.
+ SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
+ SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
+ } else {
+ // Queue this declaration so that it will be added to the
+ // translation unit scope and identifier's declaration chain
+ // once a Sema object is known.
+ PreloadedDecls.push_back(D);
+ }
+ }
+}
+
IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
if (ID == 0)
return 0;
@@ -2432,3 +2469,24 @@
UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
}
}
+
+
+PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader)
+ : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) {
+ Reader.CurrentlyLoadingTypeOrDecl = this;
+}
+
+PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() {
+ if (!Parent) {
+ // If any identifiers with corresponding top-level declarations have
+ // been loaded, load those declarations now.
+ while (!Reader.PendingIdentifierInfos.empty()) {
+ Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II,
+ Reader.PendingIdentifierInfos.front().DeclIDs,
+ true);
+ Reader.PendingIdentifierInfos.pop_front();
+ }
+ }
+
+ Reader.CurrentlyLoadingTypeOrDecl = Parent;
+}
Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=74847&r1=74846&r2=74847&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Mon Jul 6 13:54:52 2009
@@ -581,6 +581,9 @@
// after reading this declaration.
SavedStreamPosition SavedPosition(DeclsCursor);
+ // Note that we are loading a declaration record.
+ LoadingTypeOrDecl Loading(*this);
+
DeclsCursor.JumpToBit(Offset);
RecordData Record;
unsigned Code = DeclsCursor.ReadCode();
Modified: cfe/trunk/test/PCH/pr4489.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/pr4489.c?rev=74847&r1=74846&r2=74847&view=diff
==============================================================================
--- cfe/trunk/test/PCH/pr4489.c (original)
+++ cfe/trunk/test/PCH/pr4489.c Mon Jul 6 13:54:52 2009
@@ -17,4 +17,12 @@
void y(void) {
extern char z;
fprintf (0, "a");
+}
+
+struct y0 { int i; } y0[1] = {};
+
+void x0(void)
+{
+ extern char z0;
+ fprintf (0, "a");
}
\ No newline at end of file
More information about the cfe-commits
mailing list