Skip to content

Commit

Permalink
Replace Sema's map of locally-scoped extern "C" declarations with a D…
Browse files Browse the repository at this point in the history
…eclContext

of extern "C" declarations. This is simpler and vastly more efficient for
modules builds (we no longer need to load *all* extern "C" declarations to
determine if we have a redeclaration).

No functionality change intended.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@231538 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
zygoloid committed Mar 7, 2015
1 parent ff82eb5 commit 499fc53
Show file tree
Hide file tree
Showing 21 changed files with 94 additions and 123 deletions.
2 changes: 2 additions & 0 deletions include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ImportDecl *LastLocalImport;

TranslationUnitDecl *TUDecl;
mutable ExternCContextDecl *ExternCContext;

/// \brief The associated SourceManager object.a
SourceManager &SourceMgr;
Expand Down Expand Up @@ -782,6 +783,7 @@ class ASTContext : public RefCountedBase<ASTContext> {

TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }

ExternCContextDecl *getExternCContextDecl() const;

// Builtin Types.
CanQualType VoidTy;
Expand Down
2 changes: 2 additions & 0 deletions include/clang/AST/DataRecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,8 @@ DEF_TRAVERSE_DECL(
// D->getAnonymousNamespace().
})

DEF_TRAVERSE_DECL(ExternCContextDecl, {})

DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
// We shouldn't traverse an aliased namespace, since it will be
// defined (and, therefore, traversed) somewhere else.
Expand Down
37 changes: 37 additions & 0 deletions include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,43 @@ class TranslationUnitDecl : public Decl, public DeclContext {
}
};

/// \brief Declaration context for names declared as extern "C" in C++. This
/// is neither the semantic nor lexical context for such declarations, but is
/// used to check for conflicts with other extern "C" declarations. Example:
///
/// \code
/// namespace N { extern "C" void f(); } // #1
/// void N::f() {} // #2
/// namespace M { extern "C" void f(); } // #3
/// \endcode
///
/// The semantic context of #1 is namespace N and its lexical context is the
/// LinkageSpecDecl; the semantic context of #2 is namespace N and its lexical
/// context is the TU. However, both declarations are also visible in the
/// extern "C" context.
///
/// The declaration at #3 finds it is a redeclaration of \c N::f through
/// lookup in the extern "C" context.
class ExternCContextDecl : public Decl, public DeclContext {
virtual void anchor();

explicit ExternCContextDecl(TranslationUnitDecl *TU)
: Decl(ExternCContext, TU, SourceLocation()),
DeclContext(ExternCContext) {}
public:
static ExternCContextDecl *Create(const ASTContext &C,
TranslationUnitDecl *TU);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ExternCContext; }
static DeclContext *castToDeclContext(const ExternCContextDecl *D) {
return static_cast<DeclContext *>(const_cast<ExternCContextDecl*>(D));
}
static ExternCContextDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<ExternCContextDecl *>(const_cast<DeclContext*>(DC));
}
};

/// NamedDecl - This represents a decl with a name. Many decls have names such
/// as ObjCMethodDecl, but not \@class, etc.
class NamedDecl : public Decl {
Expand Down
2 changes: 2 additions & 0 deletions include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1356,6 +1356,8 @@ DEF_TRAVERSE_DECL(
// D->getAnonymousNamespace().
})

DEF_TRAVERSE_DECL(ExternCContextDecl, {})

DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
// We shouldn't traverse an aliased namespace, since it will be
// defined (and, therefore, traversed) somewhere else.
Expand Down
1 change: 1 addition & 0 deletions include/clang/Basic/DeclNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class DDecl<Decl base, bit abstract = 0> : Decl<abstract> {
class DeclContext { }

def TranslationUnit : Decl, DeclContext;
def ExternCContext : Decl, DeclContext;
def Named : Decl<1>;
def Namespace : DDecl<Named>, DeclContext;
def UsingDirective : DDecl<Named>;
Expand Down
10 changes: 0 additions & 10 deletions include/clang/Sema/ExternalSemaSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,6 @@ class ExternalSemaSource : public ExternalASTSource {
virtual void ReadUnusedLocalTypedefNameCandidates(
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {};

/// \brief Read the set of locally-scoped external declarations known to the
/// external Sema source.
///
/// The external source should append its own locally-scoped external
/// declarations to the given vector of declarations. Note that this routine
/// may be invoked multiple times; the external source should take care not
/// to introduce the same declarations repeatedly.
virtual void ReadLocallyScopedExternCDecls(
SmallVectorImpl<NamedDecl *> &Decls) {}

/// \brief Read the set of referenced selectors known to the
/// external Sema source.
///
Expand Down
10 changes: 0 additions & 10 deletions include/clang/Sema/MultiplexExternalSemaSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,6 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
void ReadUnusedLocalTypedefNameCandidates(
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;

/// \brief Read the set of locally-scoped extern "C" declarations known to the
/// external Sema source.
///
/// The external source should append its own locally-scoped external
/// declarations to the given vector of declarations. Note that this routine
/// may be invoked multiple times; the external source should take care not
/// to introduce the same declarations repeatedly.
void ReadLocallyScopedExternCDecls(
SmallVectorImpl<NamedDecl*> &Decls) override;

/// \brief Read the set of referenced selectors known to the
/// external Sema source.
///
Expand Down
27 changes: 0 additions & 27 deletions include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,33 +410,6 @@ class Sema {
/// we are currently parsing the initializer.
llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;

/// \brief A mapping from external names to the most recent
/// locally-scoped extern "C" declaration with that name.
///
/// This map contains external declarations introduced in local
/// scopes, e.g.,
///
/// \code
/// extern "C" void f() {
/// void foo(int, int);
/// }
/// \endcode
///
/// Here, the name "foo" will be associated with the declaration of
/// "foo" within f. This name is not visible outside of
/// "f". However, we still find it in two cases:
///
/// - If we are declaring another global or extern "C" entity with
/// the name "foo", we can find "foo" as a previous declaration,
/// so that the types of this external declaration can be checked
/// for compatibility.
///
/// - If we would implicitly declare "foo" (e.g., due to a call to
/// "foo" in C when no prototype or definition is visible), then
/// we find this declaration of "foo" and complain that it is
/// not visible.
llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternCDecls;

/// \brief Look for a locally scoped extern "C" declaration by the given name.
NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);

Expand Down
11 changes: 6 additions & 5 deletions include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,9 +385,7 @@ namespace clang {
/// \brief Record code for the array of tentative definitions.
TENTATIVE_DEFINITIONS = 9,

/// \brief Record code for the array of locally-scoped extern "C"
/// declarations.
LOCALLY_SCOPED_EXTERN_C_DECLS = 10,
// ID 10 used to be for a list of extern "C" declarations.

/// \brief Record code for the table of offsets into the
/// Objective-C method pool.
Expand Down Expand Up @@ -925,14 +923,17 @@ namespace clang {
PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,

/// \brief The internal '__builtin_va_list' typedef.
PREDEF_DECL_BUILTIN_VA_LIST_ID = 9
PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,

/// \brief The extern "C" context.
PREDEF_DECL_EXTERN_C_CONTEXT_ID = 10,
};

/// \brief The number of declaration IDs that are predefined.
///
/// For more information about predefined declarations, see the
/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
const unsigned int NUM_PREDEF_DECL_IDS = 10;
const unsigned int NUM_PREDEF_DECL_IDS = 11;

/// \brief Record codes for each kind of declaration.
///
Expand Down
9 changes: 0 additions & 9 deletions include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -770,12 +770,6 @@ class ASTReader
/// \brief Fields containing data that is used for semantic analysis
//@{

/// \brief The IDs of all locally scoped extern "C" decls in the chain.
///
/// Sema tracks these to validate that the types are consistent across all
/// local extern "C" declarations.
SmallVector<uint64_t, 16> LocallyScopedExternCDecls;

/// \brief The IDs of all potentially unused typedef names in the chain.
///
/// Sema tracks these to emit warnings.
Expand Down Expand Up @@ -1795,9 +1789,6 @@ class ASTReader
void ReadUnusedLocalTypedefNameCandidates(
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;

void ReadLocallyScopedExternCDecls(
SmallVectorImpl<NamedDecl *> &Decls) override;

void ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) override;

Expand Down
10 changes: 9 additions & 1 deletion lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,8 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr),
ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
FirstLocalImport(), LastLocalImport(), SourceMgr(SM), LangOpts(LOpts),
FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
SourceMgr(SM), LangOpts(LOpts),
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts),
Idents(idents), Selectors(sels), BuiltinInfo(builtins),
Expand Down Expand Up @@ -865,6 +866,13 @@ void ASTContext::PrintStats() const {
BumpAlloc.PrintStats();
}

ExternCContextDecl *ASTContext::getExternCContextDecl() const {
if (!ExternCContext)
ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl());

return ExternCContext;
}

RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
RecordDecl::TagKind TK) const {
SourceLocation Loc;
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3799,6 +3799,13 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
}

void ExternCContextDecl::anchor() { }

ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
TranslationUnitDecl *DC) {
return new (C, DC) ExternCContextDecl(DC);
}

void LabelDecl::anchor() { }

LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Block:
case Captured:
case TranslationUnit:
case ExternCContext:

case UsingDirective:
case ClassTemplateSpecialization:
Expand Down Expand Up @@ -907,6 +908,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const {
DeclContext *DeclContext::getPrimaryContext() {
switch (DeclKind) {
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::LinkageSpec:
case Decl::Block:
case Decl::Captured:
Expand Down
1 change: 1 addition & 0 deletions lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ using namespace CodeGen;
void CodeGenFunction::EmitDecl(const Decl &D) {
switch (D.getKind()) {
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::Namespace:
case Decl::UnresolvedUsingTypename:
case Decl::ClassTemplateSpecialization:
Expand Down
6 changes: 0 additions & 6 deletions lib/Sema/MultiplexExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,6 @@ void MultiplexExternalSemaSource::ReadUnusedLocalTypedefNameCandidates(
Sources[i]->ReadUnusedLocalTypedefNameCandidates(Decls);
}

void MultiplexExternalSemaSource::ReadLocallyScopedExternCDecls(
SmallVectorImpl<NamedDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadLocallyScopedExternCDecls(Decls);
}

void MultiplexExternalSemaSource::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
for(size_t i = 0; i < Sources.size(); ++i)
Expand Down
22 changes: 4 additions & 18 deletions lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4864,27 +4864,13 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) {
return;

// Note that we have a locally-scoped external with this name.
// FIXME: There can be multiple such declarations if they are functions marked
// __attribute__((overloadable)) declared in function scope in C.
LocallyScopedExternCDecls[ND->getDeclName()] = ND;
Context.getExternCContextDecl()->makeDeclVisibleInContext(ND);
}

NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
if (ExternalSource) {
// Load locally-scoped external decls from the external source.
// FIXME: This is inefficient. Maybe add a DeclContext for extern "C" decls?
SmallVector<NamedDecl *, 4> Decls;
ExternalSource->ReadLocallyScopedExternCDecls(Decls);
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
= LocallyScopedExternCDecls.find(Decls[I]->getDeclName());
if (Pos == LocallyScopedExternCDecls.end())
LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I];
}
}

NamedDecl *D = LocallyScopedExternCDecls.lookup(Name);
return D ? D->getMostRecentDecl() : nullptr;
// FIXME: We can have multiple results via __attribute__((overloadable)).
auto Result = Context.getExternCContextDecl()->lookup(Name);
return Result.empty() ? nullptr : *Result.begin();
}

/// \brief Diagnose function specifiers on a declaration of an identifier that
Expand Down
5 changes: 5 additions & 0 deletions lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
llvm_unreachable("Translation units cannot be instantiated");
}

Decl *
TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) {
llvm_unreachable("extern \"C\" context cannot be instantiated");
}

Decl *
TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) {
LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(),
Expand Down
7 changes: 6 additions & 1 deletion lib/Serialization/ASTCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) {
switch (DC->getDeclKind()) {
// These entities may have multiple definitions.
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::Namespace:
case Decl::LinkageSpec:
return nullptr;
Expand Down Expand Up @@ -149,7 +150,11 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) {

bool serialization::isRedeclarableDeclKind(unsigned Kind) {
switch (static_cast<Decl::Kind>(Kind)) {
case Decl::TranslationUnit: // Special case of a "merged" declaration.
case Decl::TranslationUnit:
case Decl::ExternCContext:
// Special case of a "merged" declaration.
return true;

case Decl::Namespace:
case Decl::NamespaceAlias:
case Decl::Typedef:
Expand Down
19 changes: 3 additions & 16 deletions lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2892,11 +2892,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;

case LOCALLY_SCOPED_EXTERN_C_DECLS:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
LocallyScopedExternCDecls.push_back(getGlobalDeclID(F, Record[I]));
break;

case SELECTOR_OFFSETS: {
F.SelectorOffsets = (const uint32_t *)Blob.data();
F.LocalNumSelectors = Record[0];
Expand Down Expand Up @@ -6284,6 +6279,9 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {

case PREDEF_DECL_BUILTIN_VA_LIST_ID:
return Context.getBuiltinVaListDecl();

case PREDEF_DECL_EXTERN_C_CONTEXT_ID:
return Context.getExternCContextDecl();
}
llvm_unreachable("PredefinedDeclIDs unknown enum value");
}
Expand Down Expand Up @@ -7326,17 +7324,6 @@ void ASTReader::ReadUnusedLocalTypedefNameCandidates(
UnusedLocalTypedefNameCandidates.clear();
}

void
ASTReader::ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl *> &Decls) {
for (unsigned I = 0, N = LocallyScopedExternCDecls.size(); I != N; ++I) {
NamedDecl *D
= dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternCDecls[I]));
if (D)
Decls.push_back(D);
}
LocallyScopedExternCDecls.clear();
}

void ASTReader::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
if (ReferencedSelectorsData.empty())
Expand Down
Loading

0 comments on commit 499fc53

Please sign in to comment.