summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/ExternalSemaSource.h4
-rw-r--r--include/clang/Sema/MultiplexExternalSemaSource.h3
-rw-r--r--include/clang/Sema/Sema.h4
-rw-r--r--include/clang/Serialization/ASTBitCodes.h6
-rw-r--r--include/clang/Serialization/ASTReader.h10
-rw-r--r--lib/Sema/MultiplexExternalSemaSource.cpp6
-rw-r--r--lib/Sema/Sema.cpp24
-rw-r--r--lib/Sema/SemaLookup.cpp2
-rw-r--r--lib/Serialization/ASTReader.cpp30
-rw-r--r--lib/Serialization/ASTWriter.cpp17
-rw-r--r--test/PCH/undefined-internal.c15
11 files changed, 97 insertions, 24 deletions
diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index a730f67984..24a4fc2a57 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -15,6 +15,7 @@
#include "clang/AST/ExternalASTSource.h"
#include "clang/Sema/Weak.h"
+#include "llvm/ADT/MapVector.h"
#include <utility>
namespace clang {
@@ -65,6 +66,9 @@ public:
/// which will be used during typo correction.
virtual void ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl *> &Namespaces);
+
+ virtual void ReadUndefinedInternals(
+ llvm::MapVector<NamedDecl*, SourceLocation> &Undefined);
/// \brief Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.
diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h
index 25db3e7a21..cb57f23cc9 100644
--- a/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -252,6 +252,9 @@ public:
/// \brief Load the set of namespaces that are known to the external source,
/// which will be used during typo correction.
virtual void ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces);
+
+ virtual void ReadUndefinedInternals(
+ llvm::MapVector<NamedDecl*, SourceLocation> &Undefined);
/// \brief Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 6c6d384a54..bbe09f777b 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -740,7 +740,7 @@ public:
/// UndefinedInternals - all the used, undefined objects with
/// internal linkage in this translation unit.
- llvm::DenseMap<NamedDecl*, SourceLocation> UndefinedInternals;
+ llvm::MapVector<NamedDecl*, SourceLocation> UndefinedInternals;
typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
@@ -2234,7 +2234,7 @@ private:
//
// The boolean value will be true to indicate that the namespace was loaded
// from an AST/PCH file, or false otherwise.
- llvm::DenseMap<NamespaceDecl*, bool> KnownNamespaces;
+ llvm::MapVector<NamespaceDecl*, bool> KnownNamespaces;
/// \brief Whether we have already loaded known namespaces from an extenal
/// source.
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 10453ec841..166434201c 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -524,7 +524,11 @@ namespace clang {
/// \brief Record of updates for a macro that was modified after
/// being deserialized.
- MACRO_UPDATES = 48
+ MACRO_UPDATES = 48,
+
+ /// \brief Record code for undefined but used internal functions and
+ /// variables.
+ UNDEFINED_INTERNALS = 49
};
/// \brief Record types used within a source manager block.
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 592556e9dc..7d4aa83b81 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -677,6 +677,9 @@ private:
/// \brief A list of the namespaces we've seen.
SmallVector<uint64_t, 4> KnownNamespaces;
+ /// \brief A list of undefined decls with internal linkage.
+ SmallVector<uint64_t, 8> UndefinedInternals;
+
/// \brief A list of modules that were imported by precompiled headers or
/// any other non-module AST file.
SmallVector<serialization::SubmoduleID, 2> ImportedModules;
@@ -1505,6 +1508,9 @@ public:
virtual void ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl *> &Namespaces);
+ virtual void ReadUndefinedInternals(
+ llvm::MapVector<NamedDecl *, SourceLocation> &Undefined);
+
virtual void ReadTentativeDefinitions(
SmallVectorImpl<VarDecl *> &TentativeDefs);
@@ -1675,13 +1681,13 @@ public:
/// \brief Read a source location.
SourceLocation ReadSourceLocation(ModuleFile &ModuleFile,
- const RecordData &Record, unsigned& Idx) {
+ const RecordData &Record, unsigned &Idx) {
return ReadSourceLocation(ModuleFile, Record[Idx++]);
}
/// \brief Read a source range.
SourceRange ReadSourceRange(ModuleFile &F,
- const RecordData &Record, unsigned& Idx);
+ const RecordData &Record, unsigned &Idx);
/// \brief Read an integral value
llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx);
diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index bee69c46e5..8df830aeff 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -200,6 +200,12 @@ void MultiplexExternalSemaSource::ReadKnownNamespaces(
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadKnownNamespaces(Namespaces);
}
+
+void MultiplexExternalSemaSource::ReadUndefinedInternals(
+ llvm::MapVector<NamedDecl*, SourceLocation> &Undefined){
+ for(size_t i = 0; i < Sources.size(); ++i)
+ Sources[i]->ReadUndefinedInternals(Undefined);
+}
bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){
for(size_t i = 0; i < Sources.size(); ++i)
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index c03d41eb04..c0482767ca 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -385,7 +385,7 @@ static void checkUndefinedInternals(Sema &S) {
// Collect all the still-undefined entities with internal linkage.
SmallVector<UndefinedInternal, 16> undefined;
- for (llvm::DenseMap<NamedDecl*,SourceLocation>::iterator
+ for (llvm::MapVector<NamedDecl*,SourceLocation>::iterator
i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end();
i != e; ++i) {
NamedDecl *decl = i->first;
@@ -407,23 +407,9 @@ static void checkUndefinedInternals(Sema &S) {
continue;
}
- // We build a FullSourceLoc so that we can sort with array_pod_sort.
- FullSourceLoc loc(i->second, S.Context.getSourceManager());
- undefined.push_back(UndefinedInternal(decl, loc));
- }
-
- if (undefined.empty()) return;
-
- // Sort (in order of use site) so that we're not (as) dependent on
- // the iteration order through an llvm::DenseMap.
- llvm::array_pod_sort(undefined.begin(), undefined.end());
-
- for (SmallVectorImpl<UndefinedInternal>::iterator
- i = undefined.begin(), e = undefined.end(); i != e; ++i) {
- NamedDecl *decl = i->decl;
S.Diag(decl->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(decl) << decl;
- S.Diag(i->useLoc, diag::note_used_here);
+ S.Diag(i->second, diag::note_used_here);
}
}
@@ -736,6 +722,8 @@ void Sema::ActOnEndOfTranslationUnit() {
}
}
+ if (ExternalSource)
+ ExternalSource->ReadUndefinedInternals(UndefinedInternals);
checkUndefinedInternals(*this);
}
@@ -1080,6 +1068,10 @@ void ExternalSemaSource::ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl *> &Namespaces) {
}
+void ExternalSemaSource::ReadUndefinedInternals(
+ llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) {
+}
+
void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
SourceLocation Loc = this->Loc;
if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 4bdc1dc253..a4228a5058 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -3857,7 +3857,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
KnownNamespaces[ExternalKnownNamespaces[I]] = true;
}
- for (llvm::DenseMap<NamespaceDecl*, bool>::iterator
+ for (llvm::MapVector<NamespaceDecl*, bool>::iterator
KNI = KnownNamespaces.begin(),
KNIEnd = KnownNamespaces.end();
KNI != KNIEnd; ++KNI)
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index fd1b8966ee..0261ad8f48 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2461,7 +2461,24 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) {
for (unsigned I = 0, N = Record.size(); I != N; ++I)
KnownNamespaces.push_back(getGlobalDeclID(F, Record[I]));
break;
-
+
+ case UNDEFINED_INTERNALS:
+ if (UndefinedInternals.size() % 2 != 0) {
+ Error("Invalid existing UndefinedInternals");
+ return true;
+ }
+
+ if (Record.size() % 2 != 0) {
+ Error("invalid undefined internals record");
+ return true;
+ }
+ for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
+ UndefinedInternals.push_back(getGlobalDeclID(F, Record[I++]));
+ UndefinedInternals.push_back(
+ ReadSourceLocation(F, Record, I).getRawEncoding());
+ }
+ break;
+
case IMPORTED_MODULES: {
if (F.Kind != MK_Module) {
// If we aren't loading a module (which has its own exports), make
@@ -5934,6 +5951,17 @@ void ASTReader::ReadKnownNamespaces(
}
}
+void ASTReader::ReadUndefinedInternals(
+ llvm::MapVector<NamedDecl*, SourceLocation> &Undefined) {
+ for (unsigned Idx = 0, N = UndefinedInternals.size(); Idx != N;) {
+ NamedDecl *D = cast<NamedDecl>(GetDecl(UndefinedInternals[Idx++]));
+ SourceLocation Loc =
+ SourceLocation::getFromRawEncoding(UndefinedInternals[Idx++]);
+ Undefined.insert(std::make_pair(D, Loc));
+ }
+}
+
+
void ASTReader::ReadTentativeDefinitions(
SmallVectorImpl<VarDecl *> &TentativeDefs) {
for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 5a690b3ded..d398153324 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -824,6 +824,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(OPENCL_EXTENSIONS);
RECORD(DELEGATING_CTORS);
RECORD(KNOWN_NAMESPACES);
+ RECORD(UNDEFINED_INTERNALS);
RECORD(MODULE_OFFSET_MAP);
RECORD(SOURCE_MANAGER_LINE_TABLE);
RECORD(OBJC_CATEGORIES_MAP);
@@ -3581,7 +3582,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Build a record containing all of the known namespaces.
RecordData KnownNamespaces;
- for (llvm::DenseMap<NamespaceDecl*, bool>::iterator
+ for (llvm::MapVector<NamespaceDecl*, bool>::iterator
I = SemaRef.KnownNamespaces.begin(),
IEnd = SemaRef.KnownNamespaces.end();
I != IEnd; ++I) {
@@ -3589,6 +3590,16 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
AddDeclRef(I->first, KnownNamespaces);
}
+ // Build a record of all used, undefined objects with internal linkage.
+ RecordData UndefinedInternals;
+ for (llvm::MapVector<NamedDecl*, SourceLocation>::iterator
+ I = SemaRef.UndefinedInternals.begin(),
+ IEnd = SemaRef.UndefinedInternals.end();
+ I != IEnd; ++I) {
+ AddDeclRef(I->first, UndefinedInternals);
+ AddSourceLocation(I->second, UndefinedInternals);
+ }
+
// Write the control block
WriteControlBlock(PP, Context, isysroot, OutputFile);
@@ -3803,6 +3814,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Write the known namespaces.
if (!KnownNamespaces.empty())
Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces);
+
+ // Write the undefined internal functions and variables.
+ if (!UndefinedInternals.empty())
+ Stream.EmitRecord(UNDEFINED_INTERNALS, UndefinedInternals);
// Write the visible updates to DeclContexts.
for (llvm::SmallPtrSet<const DeclContext *, 16>::iterator
diff --git a/test/PCH/undefined-internal.c b/test/PCH/undefined-internal.c
new file mode 100644
index 0000000000..ef514606dc
--- /dev/null
+++ b/test/PCH/undefined-internal.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -emit-pch %s -o %t
+// RUN: %clang_cc1 -include-pch %t %s -verify
+#ifndef HEADER_H
+#define HEADER_H
+static void f();
+static void g();
+void h() {
+ f();
+ g();
+}
+#else
+static void g() {}
+// expected-warning@5{{function 'f' has internal linkage but is not defined}}
+// expected-note@8{{used here}}
+#endif