return !getIdentifier();
}
+ /// \brief Returns true if this is a C++0x inline namespace.
+ bool isInline() const {
+ return false;
+ }
+
/// \brief Return the next extended namespace declaration or null if there
/// is none.
NamespaceDecl *getNextNamespace() { return NextNamespace; }
if (getKind() != Decl::Var)
return false;
if (const DeclContext *DC = getDeclContext())
- return DC->getLookupContext()->isFunctionOrMethod();
+ return DC->getRedeclContext()->isFunctionOrMethod();
return false;
}
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var)
return false;
- if (const DeclContext *DC = getDeclContext())
- return DC->getLookupContext()->isFunctionOrMethod() &&
- DC->getLookupContext()->getDeclKind() != Decl::Block;
- return false;
+ const DeclContext *DC = getDeclContext()->getRedeclContext();
+ return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
}
/// \brief Determines whether this is a static data member.
if (getKind() != Decl::Var)
return false;
- if (getDeclContext()->getLookupContext()->isFileContext())
+ if (getDeclContext()->getRedeclContext()->isFileContext())
return true;
if (isStaticDataMember())
void setLexicalDeclContext(DeclContext *DC);
- // isDefinedOutsideFunctionOrMethod - This predicate returns true if this
- // scoped decl is defined outside the current function or method. This is
- // roughly global variables and functions, but also handles enums (which could
- // be defined inside or outside a function etc).
+ /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
+ /// scoped decl is defined outside the current function or method. This is
+ /// roughly global variables and functions, but also handles enums (which
+ /// could be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const;
/// \brief Retrieves the "canonical" declaration of the given declaration.
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
- bool Equals(DeclContext *DC) {
+ bool Equals(const DeclContext *DC) const {
return DC && this->getPrimaryContext() == DC->getPrimaryContext();
}
/// \brief Determine whether this declaration context encloses the
/// declaration context DC.
- bool Encloses(DeclContext *DC);
+ bool Encloses(const DeclContext *DC) const;
/// getPrimaryContext - There may be many different
/// declarations of the same entity (including forward declarations
return const_cast<DeclContext*>(this)->getPrimaryContext();
}
- /// getLookupContext - Retrieve the innermost non-transparent
- /// context of this context, which corresponds to the innermost
- /// location from which name lookup can find the entities in this
- /// context.
- DeclContext *getLookupContext();
- const DeclContext *getLookupContext() const {
- return const_cast<DeclContext *>(this)->getLookupContext();
+ /// getRedeclContext - Retrieve the context in which an entity conflicts with
+ /// other entities of the same name, or where it is a redeclaration if the
+ /// two entities are compatible. This skips through transparent contexts,
+ /// except inline namespaces.
+ DeclContext *getRedeclContext();
+ const DeclContext *getRedeclContext() const {
+ return const_cast<DeclContext *>(this)->getRedeclContext();
}
/// \brief Retrieve the nearest enclosing namespace context.
return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
}
+ /// \brief Test if this context is part of the enclosing namespace set of
+ /// the context NS, as defined in C++0x [namespace.def]p9. If either context
+ /// isn't a namespace, this is equivalent to Equals().
+ ///
+ /// The enclosing namespace set of a namespace is the namespace and, if it is
+ /// inline, its enclosing namespace, recursively.
+ bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
+
/// getNextContext - If this is a DeclContext that may have other
/// DeclContexts that are semantically connected but syntactically
/// different, such as C++ namespaces, this routine retrieves the
}
static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
- assert(D->getDeclContext()->getLookupContext()->isFileContext() &&
+ assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
}
// Handle linkage for namespace-scope names.
- if (getDeclContext()->getLookupContext()->isFileContext())
+ if (getDeclContext()->getRedeclContext()->isFileContext())
if (Linkage L = getLinkageForNamespaceScopeDecl(this))
return L;
bool FunctionDecl::isMain() const {
ASTContext &Context = getASTContext();
return !Context.getLangOptions().Freestanding &&
- getDeclContext()->getLookupContext()->isTranslationUnit() &&
+ getDeclContext()->getRedeclContext()->isTranslationUnit() &&
getIdentifier() && getIdentifier()->isStr("main");
}
DeclContext *DeclContext::getLookupParent() {
// FIXME: Find a better way to identify friends
if (isa<FunctionDecl>(this))
- if (getParent()->getLookupContext()->isFileContext() &&
- getLexicalParent()->getLookupContext()->isRecord())
+ if (getParent()->getRedeclContext()->isFileContext() &&
+ getLexicalParent()->getRedeclContext()->isRecord())
return getLexicalParent();
return getParent();
return false;
}
-bool DeclContext::Encloses(DeclContext *DC) {
+bool DeclContext::Encloses(const DeclContext *DC) const {
if (getPrimaryContext() != this)
return getPrimaryContext()->Encloses(DC);
return const_cast<DeclContext*>(this)->lookup(Name);
}
-DeclContext *DeclContext::getLookupContext() {
+DeclContext *DeclContext::getRedeclContext() {
DeclContext *Ctx = this;
- // Skip through transparent contexts.
- while (Ctx->isTransparentContext())
+ // Skip through transparent contexts, except inline namespaces.
+ while (Ctx->isTransparentContext() && !Ctx->isNamespace())
Ctx = Ctx->getParent();
return Ctx;
}
return Ctx->getPrimaryContext();
}
+bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
+ // For non-file contexts, this is equivalent to Equals.
+ if (!isFileContext())
+ return O->Equals(this);
+
+ do {
+ if (O->Equals(this))
+ return true;
+
+ const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(O);
+ if (!NS || !NS->isInline())
+ break;
+ O = NS->getParent();
+ } while (O);
+
+ return false;
+}
+
void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
// FIXME: This feels like a hack. Should DeclarationName support
// template-ids, or is there a better way to keep specializations
const FunctionDecl *Fn) {
// Must be in global scope. Note that allocation functions can't be
// declared in namespaces.
- if (!Fn->getDeclContext()->getLookupContext()->isFileContext())
+ if (!Fn->getDeclContext()->getRedeclContext()->isFileContext())
return false;
// Signature must be void *operator new[](size_t, void*).
return CCP_Unlikely;
// Context-based decisions.
- DeclContext *DC = ND->getDeclContext()->getLookupContext();
+ DeclContext *DC = ND->getDeclContext()->getRedeclContext();
if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC))
return CCP_LocalDeclaration;
if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
/// true if 'D' belongs to the given declaration context.
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
ASTContext &Context, Scope *S) const {
- Ctx = Ctx->getLookupContext();
+ Ctx = Ctx->getRedeclContext();
if (Ctx->isFunctionOrMethod()) {
// Ignore the scopes associated within transparent declaration contexts.
return false;
}
- return D->getDeclContext()->getLookupContext()->Equals(Ctx);
+ return D->getDeclContext()->getRedeclContext()->Equals(Ctx);
}
/// AddDecl - Link the decl to its shadowed decl chain.
case NestedNameSpecifier::Namespace:
// These are always namespace scopes. We never want to enter a
// namespace scope from anything but a file context.
- return CurContext->getLookupContext()->isFileContext();
+ return CurContext->getRedeclContext()->isFileContext();
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::TypeSpec:
if (!SemaRef.getLangOptions().CPlusPlus)
return true;
- DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getLookupContext();
+ DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
// There is no way to qualify a name declared in a function or method.
if (HiddenCtx->isFunctionOrMethod())
return true;
- if (HiddenCtx == Hiding->getDeclContext()->getLookupContext())
+ if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
return true;
// We can refer to the result with the appropriate qualification. Do it.
}
else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
isa<CXXRecordDecl>(R.Declaration->getDeclContext()
- ->getLookupContext()))
+ ->getRedeclContext()))
R.QualifierIsInformative = true;
// If this result is supposed to have an informative qualifier, add one.
IsLinkageLookup = true;
} else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
IsLinkageLookup = true;
- else if (CurContext->getLookupContext()->isTranslationUnit() &&
+ else if (CurContext->getRedeclContext()->isTranslationUnit() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
IsLinkageLookup = true;
// If this is the C FILE type, notify the AST context.
if (IdentifierInfo *II = NewTD->getIdentifier())
if (!NewTD->isInvalidDecl() &&
- NewTD->getDeclContext()->getLookupContext()->isTranslationUnit()) {
+ NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (II->isStr("FILE"))
Context.setFILEDecl(NewTD);
else if (II->isStr("jmp_buf"))
isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
ASTContext &Context) {
if (!PrevDecl)
- return 0;
+ return false;
if (!PrevDecl->hasLinkage())
return false;
// outside the innermost enclosing namespace scope, the block
// scope declaration declares that same entity and receives the
// linkage of the previous declaration.
- DeclContext *OuterContext = DC->getLookupContext();
+ DeclContext *OuterContext = DC->getRedeclContext();
if (!OuterContext->isFunctionOrMethod())
// This rule only applies to block-scope declarations.
return false;
// Find the innermost enclosing namespace for the new and
// previous declarations.
- while (!OuterContext->isFileContext())
- OuterContext = OuterContext->getParent();
- while (!PrevOuterContext->isFileContext())
- PrevOuterContext = PrevOuterContext->getParent();
+ OuterContext = OuterContext->getEnclosingNamespaceContext();
+ PrevOuterContext = PrevOuterContext->getEnclosingNamespaceContext();
// The previous declaration is in a different namespace, so it
// isn't the same function.
case DeclSpec::SCS_unspecified: SC = SC_None; break;
case DeclSpec::SCS_extern: SC = SC_Extern; break;
case DeclSpec::SCS_static: {
- if (CurContext->getLookupContext()->isFunctionOrMethod()) {
+ if (CurContext->getRedeclContext()->isFunctionOrMethod()) {
// C99 6.7.1p5:
// The declaration of an identifier for a function that has
// block scope shall have no explicit storage-class specifier
if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
TagDecl *Tag = TT->getDecl();
if (Tag->getDeclName() == Name &&
- Tag->getDeclContext()->getLookupContext()
- ->Equals(TD->getDeclContext()->getLookupContext())) {
+ Tag->getDeclContext()->getRedeclContext()
+ ->Equals(TD->getDeclContext()->getRedeclContext())) {
PrevDecl = Tag;
Previous.clear();
Previous.addDecl(Tag);
if (PrevDecl)
New->setAccess(PrevDecl->getAccess());
- DeclContext *DC = New->getDeclContext()->getLookupContext();
+ DeclContext *DC = New->getDeclContext()->getRedeclContext();
DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
if (Name) // can be null along some error paths
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
// If this is the C FILE type, notify the AST context.
if (IdentifierInfo *II = New->getIdentifier())
if (!New->isInvalidDecl() &&
- New->getDeclContext()->getLookupContext()->isTranslationUnit() &&
+ New->getDeclContext()->getRedeclContext()->isTranslationUnit() &&
II->isStr("FILE"))
Context.setFILEDecl(New);
// static int a __attribute__((weakref ("v2")));
// }
// we reject them
- if (const DeclContext *Ctx = d->getDeclContext()) {
- Ctx = Ctx->getLookupContext();
- if (!isa<TranslationUnitDecl>(Ctx) && !isa<NamespaceDecl>(Ctx) ) {
- S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
- dyn_cast<NamedDecl>(d)->getNameAsString();
- return;
- }
+ const DeclContext *Ctx = d->getDeclContext()->getRedeclContext();
+ if (!Ctx->isFileContext()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
+ dyn_cast<NamedDecl>(d)->getNameAsString();
+ return;
}
// The GCC manual says
CorrectTypo(R, S, &SS, ClassDecl, 0, CTC_NoKeywords) &&
R.isSingleResult()) {
if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
- if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) {
+ if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
// member.
Namespc->setInvalidDecl();
// Continue on to push Namespc as current DeclContext and return it.
} else if (II->isStr("std") &&
- CurContext->getLookupContext()->isTranslationUnit()) {
+ CurContext->getRedeclContext()->isTranslationUnit()) {
// This is the first "real" definition of the namespace "std", so update
// our cache of the "std" namespace to point at this definition.
if (NamespaceDecl *StdNS = getStdNamespace()) {
// Link the anonymous namespace into its parent.
NamespaceDecl *PrevDecl;
- DeclContext *Parent = CurContext->getLookupContext();
+ DeclContext *Parent = CurContext->getRedeclContext();
if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
PrevDecl = TU->getAnonymousNamespace();
TU->setAnonymousNamespace(Namespc);
// allowed.
//
// That's in non-member contexts.
- if (!CurContext->getLookupContext()->isRecord())
+ if (!CurContext->getRedeclContext()->isRecord())
return false;
NestedNameSpecifier *Qual
static inline bool
CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
const FunctionDecl *FnDecl) {
- const DeclContext *DC = FnDecl->getDeclContext()->getLookupContext();
+ const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext();
if (isa<NamespaceDecl>(DC)) {
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_declared_in_namespace)
LookupResult::Filter F = Previous.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
- if (!D->getDeclContext()->getLookupContext()->Equals(DC))
+ if (!DC->InEnclosingNamespaceSetOf(
+ D->getDeclContext()->getRedeclContext()))
F.erase();
}
F.done();
// Also update the scope-based lookup if the target context's
// lookup context is in lexical scope.
if (!CurContext->isDependentContext()) {
- DC = DC->getLookupContext();
+ DC = DC->getRedeclContext();
DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
}
bool Sema::CheckObjCDeclScope(Decl *D) {
- if (isa<TranslationUnitDecl>(CurContext->getLookupContext()))
+ if (isa<TranslationUnitDecl>(CurContext->getRedeclContext()))
return false;
Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);
if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false,
Sema::CTC_NoKeywords) &&
(ReplacementField = R.getAsSingle<FieldDecl>()) &&
- ReplacementField->getDeclContext()->getLookupContext()
+ ReplacementField->getDeclContext()->getRedeclContext()
->Equals(RT->getDecl())) {
SemaRef.Diag(D->getFieldLoc(),
diag::err_field_designator_unknown_suggest)
// Friend templates are visible in fairly strange ways.
if (!CurContext->isDependentContext()) {
- DeclContext *DC = SemanticContext->getLookupContext();
+ DeclContext *DC = SemanticContext->getRedeclContext();
DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(NewTemplate, EnclosingScope,
// the explicit specialization was declared, or in a namespace
// that encloses the one in which the explicit specialization was
// declared.
- if (S.CurContext->getLookupContext()->isFunctionOrMethod()) {
+ if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
S.Diag(Loc, diag::err_template_spec_decl_function_scope)
<< Specialized;
return true;
LookupResult &Previous) {
// Remove anything from Previous that isn't a function template in
// the correct context.
- DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
+ DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
LookupResult::Filter F = Previous.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next()->getUnderlyingDecl();
if (!isa<FunctionTemplateDecl>(D) ||
- !FDLookupContext->Equals(D->getDeclContext()->getLookupContext()))
+ !FDLookupContext->InEnclosingNamespaceSetOf(
+ D->getDeclContext()->getRedeclContext()))
F.erase();
}
F.done();
// explicit function template specialization.
UnresolvedSet<8> Candidates;
- DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
+ DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *Ovl = (*I)->getUnderlyingDecl();
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
// Only consider templates found within the same semantic lookup scope as
// FD.
- if (!FDLookupContext->Equals(Ovl->getDeclContext()->getLookupContext()))
+ if (!FDLookupContext->InEnclosingNamespaceSetOf(
+ Ovl->getDeclContext()->getRedeclContext()))
continue;
// C++ [temp.expl.spec]p11:
static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
SourceLocation InstLoc,
bool WasQualifiedName) {
- DeclContext *ExpectedContext
- = D->getDeclContext()->getEnclosingNamespaceContext()->getLookupContext();
- DeclContext *CurContext = S.CurContext->getLookupContext();
+ DeclContext *OrigContext= D->getDeclContext()->getEnclosingNamespaceContext();
+ DeclContext *CurContext = S.CurContext->getRedeclContext();
if (CurContext->isRecord()) {
S.Diag(InstLoc, diag::err_explicit_instantiation_in_class)
//
// This is DR275, which we do not retroactively apply to C++98/03.
if (S.getLangOptions().CPlusPlus0x &&
- !CurContext->Encloses(ExpectedContext)) {
- if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ExpectedContext))
+ !CurContext->Encloses(OrigContext)) {
+ if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext))
S.Diag(InstLoc,
S.getLangOptions().CPlusPlus0x?
diag::err_explicit_instantiation_out_of_scope
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
return false;
}
-
+
// C++0x [temp.explicit]p2:
// If the name declared in the explicit instantiation is an unqualified
// name, the explicit instantiation shall appear in the namespace where
// namespace from its enclosing namespace set.
if (WasQualifiedName)
return false;
-
- if (CurContext->Equals(ExpectedContext))
+
+ if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
return false;
-
+
S.Diag(InstLoc,
S.getLangOptions().CPlusPlus0x?
diag::err_explicit_instantiation_unqualified_wrong_namespace
: diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
- << D << ExpectedContext;
+ << D << OrigContext;
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
return false;
}
}
if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Field->getDeclContext())) {
if (Parent->isAnonymousStructOrUnion() &&
- Parent->getLookupContext()->isFunctionOrMethod())
+ Parent->getRedeclContext()->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field);
}
// Make sure that anonymous structs and unions are recorded.
if (D->isAnonymousStructOrUnion()) {
Record->setAnonymousStructOrUnion(true);
- if (Record->getDeclContext()->getLookupContext()->isFunctionOrMethod())
+ if (Record->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
}