aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Serialization/ASTReader.h12
-rw-r--r--lib/Serialization/ASTReader.cpp49
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp24
-rw-r--r--lib/Serialization/ASTWriter.cpp18
-rw-r--r--test/Modules/Inputs/redecl-merge-left.h1
-rw-r--r--test/Modules/Inputs/redecl-merge-right.h3
-rw-r--r--test/Modules/Inputs/redecl-merge-top.h2
-rw-r--r--test/Modules/redecl-merge.m25
8 files changed, 106 insertions, 28 deletions
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 69a012cd17..b8943e7347 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -792,19 +792,13 @@ private:
/// Number of CXX base specifiers currently loaded
unsigned NumCXXBaseSpecifiersLoaded;
- /// \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;
- SmallVector<uint32_t, 4> DeclIDs;
- };
-
/// \brief The set of identifiers that were read while the AST 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;
+ llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4> >
+ PendingIdentifierInfos;
/// \brief The generation number of each identifier, which keeps track of
/// the last time we loaded information about this identifier.
@@ -1582,7 +1576,7 @@ public:
void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
void SetGloballyVisibleDecls(IdentifierInfo *II,
const SmallVectorImpl<uint32_t> &DeclIDs,
- bool Nonrecursive = false);
+ SmallVectorImpl<Decl *> *Decls = 0);
/// \brief Report a diagnostic.
DiagnosticBuilder Diag(unsigned DiagID);
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index ee558dce08..901eeb12fd 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -5830,8 +5830,8 @@ void ASTReader::InitializeSema(Sema &S) {
// Makes sure any declarations that were deserialized "too early"
// still get added to the identifier's declaration chains.
for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
- SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I],
- PreloadedDecls[I]->getDeclName());
+ NamedDecl *ND = cast<NamedDecl>(PreloadedDecls[I]->getMostRecentDecl());
+ SemaObj->pushExternalDeclIntoScope(ND, PreloadedDecls[I]->getDeclName());
}
PreloadedDecls.clear();
@@ -6208,28 +6208,32 @@ void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) {
/// \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.
+/// \param Decls if non-null, this vector will be populated with the set of
+/// deserialized declarations. These declarations will not be pushed into
+/// scope.
void
ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,
const SmallVectorImpl<uint32_t> &DeclIDs,
- bool Nonrecursive) {
- if (NumCurrentElementsDeserializing && !Nonrecursive) {
- PendingIdentifierInfos.push_back(PendingIdentifierInfo());
- PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
- PII.II = II;
- PII.DeclIDs.append(DeclIDs.begin(), DeclIDs.end());
+ SmallVectorImpl<Decl *> *Decls) {
+ if (NumCurrentElementsDeserializing && !Decls) {
+ PendingIdentifierInfos[II].append(DeclIDs.begin(), DeclIDs.end());
return;
}
for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
if (SemaObj) {
+ // If we're simply supposed to record the declarations, do so now.
+ if (Decls) {
+ Decls->push_back(D);
+ continue;
+ }
+
// 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->pushExternalDeclIntoScope(D, II);
+ NamedDecl *ND = cast<NamedDecl>(D->getMostRecentDecl());
+ SemaObj->pushExternalDeclIntoScope(ND, II);
} else {
// Queue this declaration so that it will be added to the
// translation unit scope and identifier's declaration chain
@@ -6989,10 +6993,14 @@ void ASTReader::finishPendingActions() {
!PendingMacroIDs.empty() || !PendingDeclContextInfos.empty()) {
// If any identifiers with corresponding top-level declarations have
// been loaded, load those declarations now.
+ llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> > TopLevelDecls;
while (!PendingIdentifierInfos.empty()) {
- SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
- PendingIdentifierInfos.front().DeclIDs, true);
- PendingIdentifierInfos.pop_front();
+ // FIXME: std::move
+ IdentifierInfo *II = PendingIdentifierInfos.back().first;
+ SmallVector<uint32_t, 4> DeclIDs = PendingIdentifierInfos.back().second;
+ PendingIdentifierInfos.erase(II);
+
+ SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]);
}
// Load pending declaration chains.
@@ -7002,6 +7010,17 @@ void ASTReader::finishPendingActions() {
}
PendingDeclChains.clear();
+ // Make the most recent of the top-level declarations visible.
+ for (llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> >::iterator
+ TLD = TopLevelDecls.begin(), TLDEnd = TopLevelDecls.end();
+ TLD != TLDEnd; ++TLD) {
+ IdentifierInfo *II = TLD->first;
+ for (unsigned I = 0, N = TLD->second.size(); I != N; ++I) {
+ NamedDecl *ND = cast<NamedDecl>(TLD->second[I]->getMostRecentDecl());
+ SemaObj->pushExternalDeclIntoScope(ND, II);
+ }
+ }
+
// Load any pending macro definitions.
for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) {
// FIXME: std::move here
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index ea549396f3..f4d03cf775 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1806,6 +1806,30 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
if (DC->isTranslationUnit() && Reader.SemaObj) {
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
+
+ // Temporarily consider the identifier to be up-to-date. We don't want to
+ // cause additional lookups here.
+ class UpToDateIdentifierRAII {
+ IdentifierInfo *II;
+ bool WasOutToDate;
+
+ public:
+ explicit UpToDateIdentifierRAII(IdentifierInfo *II)
+ : II(II), WasOutToDate(false)
+ {
+ if (II) {
+ WasOutToDate = II->isOutOfDate();
+ if (WasOutToDate)
+ II->setOutOfDate(false);
+ }
+ }
+
+ ~UpToDateIdentifierRAII() {
+ if (WasOutToDate)
+ II->setOutOfDate(true);
+ }
+ } UpToDate(Name.getAsIdentifierInfo());
+
for (IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
I != IEnd; ++I) {
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 79632b871a..8747bc8512 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -3141,20 +3141,32 @@ void ASTWriter::WriteRedeclarations() {
LocalRedeclChains.push_back(0); // Placeholder for the size.
// Collect the set of local redeclarations of this declaration.
- for (Decl *Prev = MostRecent; Prev != First;
+ for (Decl *Prev = MostRecent; Prev != First;
Prev = Prev->getPreviousDecl()) {
if (!Prev->isFromASTFile()) {
AddDeclRef(Prev, LocalRedeclChains);
++Size;
}
}
+
+ if (!First->isFromASTFile() && Chain) {
+ Decl *FirstFromAST = MostRecent;
+ for (Decl *Prev = MostRecent; Prev; Prev = Prev->getPreviousDecl()) {
+ if (Prev->isFromASTFile())
+ FirstFromAST = Prev;
+ }
+
+ Chain->MergedDecls[FirstFromAST].push_back(getDeclID(First));
+ }
+
LocalRedeclChains[Offset] = Size;
// Reverse the set of local redeclarations, so that we store them in
// order (since we found them in reverse order).
std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end());
- // Add the mapping from the first ID to the set of local declarations.
+ // Add the mapping from the first ID from the AST to the set of local
+ // declarations.
LocalRedeclarationsInfo Info = { getDeclID(First), Offset };
LocalRedeclsMap.push_back(Info);
@@ -3807,8 +3819,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
WriteMacroUpdates();
WriteDeclUpdatesBlocks();
WriteDeclReplacementsBlock();
- WriteMergedDecls();
WriteRedeclarations();
+ WriteMergedDecls();
WriteObjCCategories();
// Some simple statistics
diff --git a/test/Modules/Inputs/redecl-merge-left.h b/test/Modules/Inputs/redecl-merge-left.h
index cf07165a26..d66b4aa780 100644
--- a/test/Modules/Inputs/redecl-merge-left.h
+++ b/test/Modules/Inputs/redecl-merge-left.h
@@ -90,3 +90,4 @@ typedef void funcptr_with_id(int id);
@class DeclaredThenLoaded;
+void eventually_noreturn2(void);
diff --git a/test/Modules/Inputs/redecl-merge-right.h b/test/Modules/Inputs/redecl-merge-right.h
index b664ae9a72..46a16d3b13 100644
--- a/test/Modules/Inputs/redecl-merge-right.h
+++ b/test/Modules/Inputs/redecl-merge-right.h
@@ -85,3 +85,6 @@ const int one = ONE;
@interface ClassWithDef
- (void)method;
@end
+
+void eventually_noreturn(void) __attribute__((noreturn));
+void eventually_noreturn2(void) __attribute__((noreturn));
diff --git a/test/Modules/Inputs/redecl-merge-top.h b/test/Modules/Inputs/redecl-merge-top.h
index 690e6df1c9..27e71a7383 100644
--- a/test/Modules/Inputs/redecl-merge-top.h
+++ b/test/Modules/Inputs/redecl-merge-top.h
@@ -16,3 +16,5 @@ struct S2;
struct S2;
int func1(int);
+
+void eventually_noreturn(void);
diff --git a/test/Modules/redecl-merge.m b/test/Modules/redecl-merge.m
index 8937002299..e37366748d 100644
--- a/test/Modules/redecl-merge.m
+++ b/test/Modules/redecl-merge.m
@@ -1,5 +1,6 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify -Wno-objc-root-class
+// RUN: %clang_cc1 -fmodules -Wreturn-type -fmodules-cache-path=%t -I %S/Inputs %s -verify -Wno-objc-root-class
+
@class C2;
@class C3;
@class C3;
@@ -8,8 +9,28 @@ typedef struct my_struct_type *my_struct_ref;
@protocol P4;
@class C3;
@class C3;
+
+int *call_eventually_noreturn(void) {
+ eventually_noreturn();
+} // expected-warning{{control reaches end of non-void function}}
+
+int *call_eventually_noreturn2(void) {
+ eventually_noreturn2();
+} // expected-warning{{control reaches end of non-void function}}
+
@import redecl_merge_right;
+int *call_eventually_noreturn_again(void) {
+ eventually_noreturn();
+}
+
+int *call_eventually_noreturn2_again(void) {
+ // noreturn and non-noreturn functions have different types
+ eventually_noreturn2(); // expected-error{{call to 'eventually_noreturn2' is ambiguous}}
+ // expected-note@93{{candidate function}}
+ // expected-note@90{{candidate function}}
+}
+
@implementation A
- (Super*)init { return self; }
@end
@@ -148,3 +169,5 @@ id<P3> p3;
// Make sure we don't get conflicts with 'id'.
funcptr_with_id fid;
id id_global;
+
+