Introduce support for "transparent" DeclContexts, which are
DeclContexts whose members are visible from enclosing DeclContexts up
to (and including) the innermost enclosing non-transparent
DeclContexts. Transparent DeclContexts unify the mechanism to be used
for various language features, including C enumerations, anonymous
unions, C++0x inline namespaces, and C++ linkage
specifications. Please refer to the documentation in the Clang
internals manual for more information.
Only enumerations and linkage specifications currently use transparent
DeclContexts.
Still to do: use transparent DeclContexts to implement anonymous
unions and GCC's anonymous structs extension, and, later, the C++0x
features. We also need to tighten up the DeclContext/ScopedDecl link
to ensure that every ScopedDecl is in a single DeclContext, which
will ensure that we can then enforce ownership and reduce the memory
footprint of DeclContext.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61735 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index c6b3c53..59d8a07 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -406,10 +406,24 @@
}
}
+bool DeclContext::isTransparentContext() const {
+ if (DeclKind == Decl::Enum)
+ return true; // FIXME: Check for C++0x scoped enums
+ else if (DeclKind == Decl::LinkageSpec)
+ return true;
+ else if (DeclKind == Decl::Record || DeclKind == Decl::CXXRecord)
+ return false; // FIXME: need to know about anonymous unions/structs
+ else if (DeclKind == Decl::Namespace)
+ return false; // FIXME: Check for C++0x inline namespaces
+
+ return false;
+}
+
DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) {
switch (DeclKind) {
- case Decl::Block:
case Decl::TranslationUnit:
+ case Decl::LinkageSpec:
+ case Decl::Block:
// There is only one DeclContext for these entities.
return this;
@@ -418,10 +432,15 @@
return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
case Decl::Enum:
+#if 0
+ // FIXME: See the comment for CXXRecord, below.
// The declaration associated with the enumeration type is our
// primary context.
return Context.getTypeDeclType(static_cast<EnumDecl*>(this))
->getAsEnumType()->getDecl();
+#else
+ return this;
+#endif
case Decl::Record:
case Decl::CXXRecord: {
@@ -461,13 +480,14 @@
DeclContext *DeclContext::getNextContext() {
switch (DeclKind) {
- case Decl::Block:
case Decl::TranslationUnit:
case Decl::Enum:
case Decl::Record:
case Decl::CXXRecord:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
+ case Decl::LinkageSpec:
+ case Decl::Block:
// There is only one DeclContext for these entities.
return 0;
@@ -488,6 +508,24 @@
D->getDeclContext()->insert(Context, D);
}
+/// buildLookup - Build the lookup data structure with all of the
+/// declarations in DCtx (and any other contexts linked to it or
+/// transparent contexts nested within it).
+void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) {
+ for (; DCtx; DCtx = DCtx->getNextContext()) {
+ for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D) {
+ // Insert this declaration into the lookup structure
+ insertImpl(*D);
+
+ // If this declaration is itself a transparent declaration context,
+ // add its members (recursively).
+ if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
+ if (InnerCtx->isTransparentContext())
+ buildLookup(Context, InnerCtx->getPrimaryContext(Context));
+ }
+ }
+}
+
DeclContext::lookup_result
DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
DeclContext *PrimaryContext = getPrimaryContext(Context);
@@ -497,11 +535,8 @@
/// If there is no lookup data structure, build one now by walking
/// all of the linked DeclContexts (in declaration order!) and
/// inserting their values.
- if (LookupPtr.getPointer() == 0) {
- for (DeclContext *DCtx = this; DCtx; DCtx = DCtx->getNextContext())
- for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D)
- insertImpl(*D);
- }
+ if (LookupPtr.getPointer() == 0)
+ buildLookup(Context, this);
if (isLookupMap()) {
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
@@ -543,9 +578,19 @@
// someone asks for it.
if (LookupPtr.getPointer())
insertImpl(D);
+
+
+ // If we are a transparent context, insert into our parent context,
+ // too. This operation is recursive.
+ if (isTransparentContext())
+ getParent()->insert(Context, D);
}
void DeclContext::insertImpl(ScopedDecl *D) {
+ // Skip unnamed declarations.
+ if (!D->getDeclName())
+ return;
+
bool MayBeRedeclaration = true;
if (!isLookupMap()) {
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 27065a7..66afac8 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -291,42 +291,10 @@
return new (Mem) OverloadedFunctionDecl(DC, N);
}
-LinkageSpecDecl::LinkageSpecDecl(SourceLocation L, LanguageIDs lang,
- Decl **InDecls, unsigned InNumDecls)
- : Decl(LinkageSpec, L), Language(lang), HadBraces(true),
- Decls(0), NumDecls(InNumDecls) {
- Decl **NewDecls = new Decl*[NumDecls];
- for (unsigned I = 0; I < NumDecls; ++I)
- NewDecls[I] = InDecls[I];
- Decls = NewDecls;
-}
-
-LinkageSpecDecl::~LinkageSpecDecl() {
- if (HadBraces)
- delete [] (Decl**)Decls;
-}
-
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
+ DeclContext *DC,
SourceLocation L,
- LanguageIDs Lang, Decl *D) {
+ LanguageIDs Lang, bool Braces) {
void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
- return new (Mem) LinkageSpecDecl(L, Lang, D);
-}
-
-LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
- SourceLocation L,
- LanguageIDs Lang,
- Decl **Decls, unsigned NumDecls) {
- void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
- return new (Mem) LinkageSpecDecl(L, Lang, Decls, NumDecls);
-}
-
-LinkageSpecDecl::decl_const_iterator LinkageSpecDecl::decls_begin() const {
- if (hasBraces()) return (Decl**)Decls;
- else return (Decl**)&Decls;
-}
-
-LinkageSpecDecl::decl_iterator LinkageSpecDecl::decls_end() const {
- if (hasBraces()) return (Decl**)Decls + NumDecls;
- else return (Decl**)&Decls + 1;
+ return new (Mem) LinkageSpecDecl(DC, L, Lang, Braces);
}
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 68412f9..0a29813 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -686,29 +686,12 @@
Decl::EmitInRec(S);
S.EmitInt(getLanguage());
S.EmitBool(HadBraces);
- if (HadBraces) {
- S.EmitInt(NumDecls);
- for (decl_const_iterator D = decls_begin(), DEnd = decls_end();
- D != DEnd; ++D)
- S.EmitPtr(*D);
- } else {
- S.EmitPtr((Decl*)Decls);
- }
}
void LinkageSpecDecl::ReadInRec(Deserializer& D, ASTContext& C) {
Decl::ReadInRec(D, C);
Language = static_cast<LanguageIDs>(D.ReadInt());
HadBraces = D.ReadBool();
- if (HadBraces) {
- NumDecls = D.ReadInt();
- Decl **NewDecls = new Decl*[NumDecls];
- Decls = NewDecls;
- for (unsigned I = 0; I < NumDecls; ++I)
- D.ReadPtr(NewDecls[I]);
- } else {
- D.ReadPtr(this->Decls);
- }
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index c063654..a2fdf41 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1123,6 +1123,10 @@
/// identifier
///
void Parser::ParseEnumBody(SourceLocation StartLoc, DeclTy *EnumDecl) {
+ // Enter the scope of the enum body and start the definition.
+ ParseScope EnumScope(this, Scope::DeclScope);
+ Actions.ActOnEnumStartDefinition(CurScope, EnumDecl);
+
SourceLocation LBraceLoc = ConsumeBrace();
// C does not allow an empty enumerator-list, C++ does [dcl.enum].
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 3236763..0b06006 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -108,27 +108,28 @@
unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);
SourceLocation Loc = ConsumeStringToken();
- DeclTy *D = 0;
-
- if (Tok.isNot(tok::l_brace)) {
- D = ParseDeclarationOrFunctionDefinition();
- if (D)
- return Actions.ActOnLinkageSpec(Loc, LangBufPtr, StrSize, D);
- return 0;
+ ParseScope LinkageScope(this, Scope::DeclScope);
+ DeclTy *LinkageSpec
+ = Actions.ActOnStartLinkageSpecification(CurScope,
+ /*FIXME: */SourceLocation(),
+ Loc, LangBufPtr, StrSize,
+ Tok.is(tok::l_brace)? Tok.getLocation()
+ : SourceLocation());
+
+ if (Tok.isNot(tok::l_brace)) {
+ ParseDeclarationOrFunctionDefinition();
+ return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
+ SourceLocation());
}
SourceLocation LBrace = ConsumeBrace();
- llvm::SmallVector<DeclTy *, 8> InnerDecls;
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
- D = ParseExternalDeclaration();
- if (D)
- InnerDecls.push_back(D);
+ ParseExternalDeclaration();
}
SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
- return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize,
- &InnerDecls.front(), InnerDecls.size());
+ return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, RBrace);
}
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 027beed..18e78a0 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -60,6 +60,9 @@
else
return TUCtx();
+ while (Ctx->isTransparentContext())
+ Ctx = Ctx->getParent();
+
if (isa<TranslationUnitDecl>(Ctx))
return TUCtx();
@@ -83,30 +86,12 @@
// IdDeclInfo Implementation
//===----------------------------------------------------------------------===//
-/// FindContext - Returns an iterator pointing just after the decl that is
-/// in the given context or in a parent of it. The search is in reverse
-/// order, from end to begin.
-IdentifierResolver::IdDeclInfo::DeclsTy::iterator
-IdentifierResolver::IdDeclInfo::FindDeclVisibleInContext(
- const LookupContext &Ctx,
- const DeclsTy::iterator &Start) {
- for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) {
- if (Ctx.isEqOrContainedBy(LookupContext(*(I-1))))
- return I;
- }
-
- return Decls.begin();
-}
-
/// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
/// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
/// be already added to the scope chain and must be in the same context as
/// the decl that we want to add.
void IdentifierResolver::IdDeclInfo::AddShadowed(NamedDecl *D,
NamedDecl *Shadow) {
- assert(LookupContext(D) == LookupContext(Shadow) &&
- "Decl and Shadow not in same context!");
-
for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
if (Shadow == *(I-1)) {
Decls.insert(I-1, D);
@@ -147,7 +132,15 @@
/// true if 'D' belongs to the given declaration context.
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
ASTContext &Context, Scope *S) const {
+ while (Ctx->isTransparentContext())
+ Ctx = Ctx->getParent();
+
if (Ctx->isFunctionOrMethod()) {
+ // Ignore the scopes associated within transparent declaration contexts.
+ while (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext())
+ S = S->getParent();
+
if (S->isDeclScope(D))
return true;
if (LangOpt.CPlusPlus) {
@@ -201,7 +194,6 @@
/// encountered before the 'D' decl.
void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
assert(D->getDeclName() == Shadow->getDeclName() && "Different ids!");
- assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
DeclarationName Name = D->getDeclName();
void *Ptr = Name.getFETokenInfo<void>();
@@ -252,30 +244,14 @@
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) return end();
- LookupContext LC(Ctx);
-
if (isDeclPtr(Ptr)) {
NamedDecl *D = static_cast<NamedDecl*>(Ptr);
- LookupContext DC(D);
-
- if (( LookInParentCtx && LC.isEqOrContainedBy(DC)) ||
- (!LookInParentCtx && LC == DC))
- return iterator(D);
- else
- return end();
+ return iterator(D);
}
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
- IdDeclInfo::DeclsTy::iterator I;
- if (LookInParentCtx)
- I = IDI->FindDeclVisibleInContext(LC);
- else {
- for (I = IDI->decls_end(); I != IDI->decls_begin(); --I)
- if (LookupContext(*(I-1)) == LC)
- break;
- }
-
+ IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
if (I != IDI->decls_begin())
return iterator(I-1, LookInParentCtx);
else // No decls found.
@@ -285,22 +261,11 @@
/// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
void IdentifierResolver::iterator::PreIncIter() {
NamedDecl *D = **this;
- LookupContext Ctx(D);
void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
BaseIter I = getIterator();
- if (LookInParentCtx())
- I = Info->FindDeclVisibleInContext(Ctx, I);
- else {
- if (I != Info->decls_begin() && LookupContext(*(I-1)) != Ctx) {
- // The next decl is in different declaration context.
- // Skip remaining decls and set the iterator to the end.
- I = Info->decls_begin();
- }
- }
-
if (I != Info->decls_begin())
*this = iterator(I-1, LookInParentCtx());
else // No more decls.
diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h
index 30846dc..3dab1b5 100644
--- a/lib/Sema/IdentifierResolver.h
+++ b/lib/Sema/IdentifierResolver.h
@@ -91,22 +91,7 @@
inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
inline DeclsTy::iterator decls_end() { return Decls.end(); }
- /// FindContext - Returns an iterator pointing just after the decl that is
- /// in the given context or in a parent of it. The search is in reverse
- /// order, from end to begin.
- DeclsTy::iterator FindDeclVisibleInContext(const LookupContext &Ctx) {
- return FindDeclVisibleInContext(Ctx, Decls.end());
- }
-
- /// FindContext - Returns an iterator pointing just after the decl that is
- /// in the given context or in a parent of it. The search is in reverse
- /// order, from end to begin.
- DeclsTy::iterator FindDeclVisibleInContext(const LookupContext &Ctx,
- const DeclsTy::iterator &Start);
-
- void AddDecl(NamedDecl *D) {
- Decls.insert(FindDeclVisibleInContext(LookupContext(D)), D);
- }
+ void AddDecl(NamedDecl *D) { Decls.push_back(D); }
/// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
/// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index ca15176..d3f373f 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -288,12 +288,6 @@
virtual void ObjCActOnStartOfMethodDef(Scope *S, DeclTy *D);
virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtArg Body);
- virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace,
- SourceLocation RBrace, const char *Lang,
- unsigned StrSize,
- DeclTy **Decls, unsigned NumDecls);
- virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang,
- unsigned StrSize, DeclTy *D);
virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr);
/// Scope actions.
@@ -326,6 +320,7 @@
DeclTy **Fields, unsigned NumFields,
SourceLocation LBrac, SourceLocation RBrac,
AttributeList *AttrList);
+ virtual void ActOnEnumStartDefinition(Scope *S, DeclTy *EnumDecl);
virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
DeclTy *LastEnumConstant,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -980,6 +975,20 @@
SourceLocation RParenLoc);
//===--------------------------------------------------------------------===//
+ // C++ Declarations
+ //
+ virtual DeclTy *ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation LangLoc,
+ const char *Lang,
+ unsigned StrSize,
+ SourceLocation LBraceLoc);
+ virtual DeclTy *ActOnFinishLinkageSpecification(Scope *S,
+ DeclTy *LinkageSpec,
+ SourceLocation RBraceLoc);
+
+
+ //===--------------------------------------------------------------------===//
// C++ Classes
//
virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 21d3ad6..f4677f0 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -93,6 +93,13 @@
/// Add this decl to the scope shadowed decl chains.
void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
+ // Move up the scope chain until we find the nearest enclosing
+ // non-transparent context. The declaration will be introduced into this
+ // scope.
+ while (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext())
+ S = S->getParent();
+
S->AddDecl(D);
// Add scoped declarations into their context, so that they can be
@@ -149,8 +156,11 @@
// We are pushing the name of a function, which might be an
// overloaded name.
FunctionDecl *FD = cast<FunctionDecl>(D);
+ DeclContext *DC = FD->getDeclContext();
+ while (DC->isTransparentContext())
+ DC = DC->getParent();
IdentifierResolver::iterator Redecl
- = std::find_if(IdResolver.begin(FD->getDeclName(), CurContext,
+ = std::find_if(IdResolver.begin(FD->getDeclName(), DC,
false/*LookInParentCtx*/),
IdResolver.end(),
std::bind1st(std::mem_fun(&ScopedDecl::declarationReplaces),
@@ -337,7 +347,7 @@
Ctx = Ctx->getParent();
}
- if (!LookInParent)
+ if (!LookInParent && !Ctx->isTransparentContext())
return 0;
}
}
@@ -3117,6 +3127,15 @@
ProcessDeclAttributeList(Record, Attr);
}
+void Sema::ActOnEnumStartDefinition(Scope *S, DeclTy *EnumD) {
+ EnumDecl *Enum = cast_or_null<EnumDecl>((Decl *)EnumD);
+
+ if (Enum) {
+ // Enter the enumeration context.
+ PushDeclContext(S, Enum);
+ }
+}
+
Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
DeclTy *lastEnumConst,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -3212,20 +3231,22 @@
void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
DeclTy **Elements, unsigned NumElements) {
EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
+ QualType EnumType = Context.getTypeDeclType(Enum);
- if (Enum) {
- if (EnumDecl *Def = cast_or_null<EnumDecl>(Enum->getDefinition(Context))) {
- // Diagnose code like:
- // enum e0 {
- // E0 = sizeof(enum e0 { E1 })
- // };
- Diag(Def->getLocation(), diag::err_nested_redefinition)
- << Enum->getDeclName();
- Diag(Enum->getLocation(), diag::note_previous_definition);
- Enum->setInvalidDecl();
- return;
- }
+ if (EnumType->getAsEnumType()->getDecl()->isDefinition()) {
+ EnumDecl *Def = EnumType->getAsEnumType()->getDecl();
+ // Diagnose code like:
+ // enum e0 {
+ // E0 = sizeof(enum e0 { E1 })
+ // };
+ Diag(Def->getLocation(), diag::err_nested_redefinition)
+ << Enum->getDeclName();
+ Diag(Enum->getLocation(), diag::note_previous_definition);
+ Enum->setInvalidDecl();
+ PopDeclContext();
+ return;
}
+
// TODO: If the result value doesn't fit in an int, it must be a long or long
// long value. ISO C does not support this, but GCC does as an extension,
// emit a warning.
@@ -3239,7 +3260,6 @@
// Keep track of whether all elements have type int.
bool AllElementsInt = true;
- QualType EnumType = Context.getTypeDeclType(Enum);
EnumConstantDecl *EltList = 0;
for (unsigned i = 0; i != NumElements; ++i) {
EnumConstantDecl *ECD =
@@ -3392,6 +3412,9 @@
Enum->completeDefinition(Context, BestType);
Consumer.HandleTagDeclDefinition(Enum);
+
+ // Leave the context of the enumeration.
+ PopDeclContext();
}
Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e3c8373..7c05f6b 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2003,48 +2003,49 @@
return false;
}
-/// ActOnLinkageSpec - Parsed a C++ linkage-specification that
-/// contained braces. Lang/StrSize contains the language string that
-/// was parsed at location Loc. Decls/NumDecls provides the
-/// declarations parsed inside the linkage specification.
-Sema::DeclTy *Sema::ActOnLinkageSpec(SourceLocation Loc,
- SourceLocation LBrace,
- SourceLocation RBrace,
- const char *Lang,
- unsigned StrSize,
- DeclTy **Decls, unsigned NumDecls) {
+/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
+/// linkage specification, including the language and (if present)
+/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
+/// the location of the language string literal, which is provided
+/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+/// the '{' brace. Otherwise, this linkage specification does not
+/// have any braces.
+Sema::DeclTy *Sema::ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation LangLoc,
+ const char *Lang,
+ unsigned StrSize,
+ SourceLocation LBraceLoc) {
LinkageSpecDecl::LanguageIDs Language;
if (strncmp(Lang, "\"C\"", StrSize) == 0)
Language = LinkageSpecDecl::lang_c;
else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
Language = LinkageSpecDecl::lang_cxx;
else {
- Diag(Loc, diag::err_bad_language);
+ Diag(LangLoc, diag::err_bad_language);
return 0;
}
// FIXME: Add all the various semantics of linkage specifications
- return LinkageSpecDecl::Create(Context, Loc, Language,
- (Decl **)Decls, NumDecls);
+ LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
+ LangLoc, Language,
+ LBraceLoc.isValid());
+ CurContext->addDecl(Context, D);
+ PushDeclContext(S, D);
+ return D;
}
-Sema::DeclTy *Sema::ActOnLinkageSpec(SourceLocation Loc,
- const char *Lang, unsigned StrSize,
- DeclTy *D) {
- LinkageSpecDecl::LanguageIDs Language;
- Decl *dcl = static_cast<Decl *>(D);
- if (strncmp(Lang, "\"C\"", StrSize) == 0)
- Language = LinkageSpecDecl::lang_c;
- else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
- Language = LinkageSpecDecl::lang_cxx;
- else {
- Diag(Loc, diag::err_bad_language);
- return 0;
- }
-
- // FIXME: Add all the various semantics of linkage specifications
- return LinkageSpecDecl::Create(Context, Loc, Language, dcl);
+/// ActOnFinishLinkageSpecification - Completely the definition of
+/// the C++ linkage specification LinkageSpec. If RBraceLoc is
+/// valid, it's the position of the closing '}' brace in a linkage
+/// specification that uses braces.
+Sema::DeclTy *Sema::ActOnFinishLinkageSpecification(Scope *S,
+ DeclTy *LinkageSpec,
+ SourceLocation RBraceLoc) {
+ if (LinkageSpec)
+ PopDeclContext();
+ return LinkageSpec;
}
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch