From: Nick Lewycky Date: Sat, 26 Jan 2013 00:35:08 +0000 (+0000) Subject: Preserve Sema::UndefinedInternals across PCH boundaries. Fixes X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8334af8c2a88e59860e7aef2ec44a64df402cae1;p=platform%2Fupstream%2Fllvm.git Preserve Sema::UndefinedInternals across PCH boundaries. Fixes -Wundefined-internal warnings with PCH. llvm-svn: 173538 --- diff --git a/clang/include/clang/Sema/ExternalSemaSource.h b/clang/include/clang/Sema/ExternalSemaSource.h index a730f67..24a4fc2 100644 --- a/clang/include/clang/Sema/ExternalSemaSource.h +++ b/clang/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 namespace clang { @@ -65,6 +66,9 @@ public: /// which will be used during typo correction. virtual void ReadKnownNamespaces( SmallVectorImpl &Namespaces); + + virtual void ReadUndefinedInternals( + llvm::MapVector &Undefined); /// \brief Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 25db3e7..cb57f23 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/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 &Namespaces); + + virtual void ReadUndefinedInternals( + llvm::MapVector &Undefined); /// \brief Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6c6d384..bbe09f7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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 UndefinedInternals; + llvm::MapVector UndefinedInternals; typedef std::pair GlobalMethods; typedef llvm::DenseMap 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 KnownNamespaces; + llvm::MapVector KnownNamespaces; /// \brief Whether we have already loaded known namespaces from an extenal /// source. diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 10453ec..1664342 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/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/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 592556e..7d4aa83 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -677,6 +677,9 @@ private: /// \brief A list of the namespaces we've seen. SmallVector KnownNamespaces; + /// \brief A list of undefined decls with internal linkage. + SmallVector UndefinedInternals; + /// \brief A list of modules that were imported by precompiled headers or /// any other non-module AST file. SmallVector ImportedModules; @@ -1505,6 +1508,9 @@ public: virtual void ReadKnownNamespaces( SmallVectorImpl &Namespaces); + virtual void ReadUndefinedInternals( + llvm::MapVector &Undefined); + virtual void ReadTentativeDefinitions( SmallVectorImpl &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/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index bee69c4..8df830a 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/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 &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/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index c03d41e..c048276 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -385,7 +385,7 @@ static void checkUndefinedInternals(Sema &S) { // Collect all the still-undefined entities with internal linkage. SmallVector undefined; - for (llvm::DenseMap::iterator + for (llvm::MapVector::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::iterator - i = undefined.begin(), e = undefined.end(); i != e; ++i) { - NamedDecl *decl = i->decl; S.Diag(decl->getLocation(), diag::warn_undefined_internal) << isa(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 &Namespaces) { } +void ExternalSemaSource::ReadUndefinedInternals( + llvm::MapVector &Undefined) { +} + void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { SourceLocation Loc = this->Loc; if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation(); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 4bdc1dc..a4228a5 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3857,7 +3857,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, KnownNamespaces[ExternalKnownNamespaces[I]] = true; } - for (llvm::DenseMap::iterator + for (llvm::MapVector::iterator KNI = KnownNamespaces.begin(), KNIEnd = KnownNamespaces.end(); KNI != KNIEnd; ++KNI) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index fd1b896..0261ad8 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/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 &Undefined) { + for (unsigned Idx = 0, N = UndefinedInternals.size(); Idx != N;) { + NamedDecl *D = cast(GetDecl(UndefinedInternals[Idx++])); + SourceLocation Loc = + SourceLocation::getFromRawEncoding(UndefinedInternals[Idx++]); + Undefined.insert(std::make_pair(D, Loc)); + } +} + + void ASTReader::ReadTentativeDefinitions( SmallVectorImpl &TentativeDefs) { for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 5a690b3..d398153 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/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::iterator + for (llvm::MapVector::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::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::iterator diff --git a/clang/test/PCH/undefined-internal.c b/clang/test/PCH/undefined-internal.c new file mode 100644 index 0000000..ef51460 --- /dev/null +++ b/clang/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