forked from OSchip/llvm-project
Instead of hanging a using declaration's target decls directly off the using
decl, create shadow declarations and put them in scope like normal. Work in progress. llvm-svn: 89048
This commit is contained in:
parent
d6ea9028e7
commit
3f746828d7
|
@ -79,9 +79,11 @@ public:
|
|||
/// namespaces, labels, tags, members and ordinary
|
||||
/// identifiers. These are meant as bitmasks, so that searches in
|
||||
/// C++ can look into the "tag" namespace during ordinary lookup. We
|
||||
/// use additional namespaces for Objective-C entities. We also
|
||||
/// put C++ friend declarations (of previously-undeclared entities) in
|
||||
/// shadow namespaces.
|
||||
/// use additional namespaces for Objective-C entities. We also put
|
||||
/// C++ friend declarations (of previously-undeclared entities) in
|
||||
/// shadow namespaces, and 'using' declarations (as opposed to their
|
||||
/// implicit shadow declarations) can be found in their own
|
||||
/// namespace.
|
||||
enum IdentifierNamespace {
|
||||
IDNS_Label = 0x1,
|
||||
IDNS_Tag = 0x2,
|
||||
|
@ -91,7 +93,8 @@ public:
|
|||
IDNS_ObjCImplementation = 0x20,
|
||||
IDNS_ObjCCategoryImpl = 0x40,
|
||||
IDNS_OrdinaryFriend = 0x80,
|
||||
IDNS_TagFriend = 0x100
|
||||
IDNS_TagFriend = 0x100,
|
||||
IDNS_Using = 0x200
|
||||
};
|
||||
|
||||
/// ObjCDeclQualifier - Qualifier used on types in method declarations
|
||||
|
|
|
@ -1644,6 +1644,56 @@ public:
|
|||
static bool classof(const NamespaceAliasDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// UsingShadowDecl - Represents a shadow declaration introduced into
|
||||
/// a scope by a (resolved) using declaration. For example,
|
||||
///
|
||||
/// namespace A {
|
||||
/// void foo();
|
||||
/// }
|
||||
/// namespace B {
|
||||
/// using A::foo(); // <- a UsingDecl
|
||||
/// // Also creates a UsingShadowDecl for A::foo in B
|
||||
/// }
|
||||
///
|
||||
class UsingShadowDecl : public NamedDecl {
|
||||
/// The referenced declaration.
|
||||
NamedDecl *Underlying;
|
||||
|
||||
/// The using declaration which introduced this decl.
|
||||
UsingDecl *Using;
|
||||
|
||||
UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using,
|
||||
NamedDecl *Target)
|
||||
: NamedDecl(UsingShadow, DC, Loc, Target->getDeclName()),
|
||||
Underlying(Target), Using(Using) {
|
||||
IdentifierNamespace = Target->getIdentifierNamespace();
|
||||
setImplicit();
|
||||
}
|
||||
|
||||
public:
|
||||
static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation Loc, UsingDecl *Using,
|
||||
NamedDecl *Target) {
|
||||
return new (C) UsingShadowDecl(DC, Loc, Using, Target);
|
||||
}
|
||||
|
||||
/// Gets the underlying declaration which has been brought into the
|
||||
/// local scope.
|
||||
NamedDecl *getTargetDecl() const {
|
||||
return Underlying;
|
||||
}
|
||||
|
||||
/// Gets the using declaration to which this declaration is tied.
|
||||
UsingDecl *getUsingDecl() const {
|
||||
return Using;
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::UsingShadow;
|
||||
}
|
||||
static bool classof(const UsingShadowDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// UsingDecl - Represents a C++ using-declaration. For example:
|
||||
/// using someNameSpace::someIdentifier;
|
||||
class UsingDecl : public NamedDecl {
|
||||
|
@ -1651,29 +1701,26 @@ class UsingDecl : public NamedDecl {
|
|||
/// preceding the declaration name.
|
||||
SourceRange NestedNameRange;
|
||||
|
||||
/// \brief The source location of the target declaration name.
|
||||
SourceLocation TargetNameLocation;
|
||||
|
||||
/// \brief The source location of the "using" location itself.
|
||||
SourceLocation UsingLocation;
|
||||
|
||||
/// \brief Target declaration.
|
||||
NamedDecl* TargetDecl;
|
||||
|
||||
/// \brief Target nested name specifier.
|
||||
NestedNameSpecifier* TargetNestedNameDecl;
|
||||
NestedNameSpecifier* TargetNestedName;
|
||||
|
||||
/// \brief The collection of shadow declarations associated with
|
||||
/// this using declaration. This set can change as a class is
|
||||
/// processed.
|
||||
llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows;
|
||||
|
||||
// \brief Has 'typename' keyword.
|
||||
bool IsTypeName;
|
||||
|
||||
UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
|
||||
SourceLocation TargetNL, SourceLocation UL, NamedDecl* Target,
|
||||
NestedNameSpecifier* TargetNNS, bool IsTypeNameArg)
|
||||
: NamedDecl(Decl::Using, DC, L, Target->getDeclName()),
|
||||
NestedNameRange(NNR), TargetNameLocation(TargetNL),
|
||||
UsingLocation(UL), TargetDecl(Target),
|
||||
TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) {
|
||||
this->IdentifierNamespace = TargetDecl->getIdentifierNamespace();
|
||||
SourceLocation UL, NestedNameSpecifier* TargetNNS,
|
||||
DeclarationName Name, bool IsTypeNameArg)
|
||||
: NamedDecl(Decl::Using, DC, L, Name),
|
||||
NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
|
||||
IsTypeName(IsTypeNameArg) {
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -1681,28 +1728,37 @@ public:
|
|||
/// preceding the namespace name.
|
||||
SourceRange getNestedNameRange() { return NestedNameRange; }
|
||||
|
||||
/// \brief Returns the source location of the target declaration name.
|
||||
SourceLocation getTargetNameLocation() { return TargetNameLocation; }
|
||||
|
||||
/// \brief Returns the source location of the "using" location itself.
|
||||
SourceLocation getUsingLocation() { return UsingLocation; }
|
||||
|
||||
/// \brief getTargetDecl - Returns target specified by using-decl.
|
||||
NamedDecl *getTargetDecl() { return TargetDecl; }
|
||||
const NamedDecl *getTargetDecl() const { return TargetDecl; }
|
||||
|
||||
/// \brief Get target nested name declaration.
|
||||
NestedNameSpecifier* getTargetNestedNameDecl() {
|
||||
return TargetNestedNameDecl;
|
||||
return TargetNestedName;
|
||||
}
|
||||
|
||||
/// isTypeName - Return true if using decl has 'typename'.
|
||||
bool isTypeName() const { return IsTypeName; }
|
||||
|
||||
typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator;
|
||||
shadow_iterator shadow_begin() const { return Shadows.begin(); }
|
||||
shadow_iterator shadow_end() const { return Shadows.end(); }
|
||||
|
||||
void addShadowDecl(UsingShadowDecl *S) {
|
||||
assert(S->getUsingDecl() == this);
|
||||
if (!Shadows.insert(S)) {
|
||||
assert(false && "declaration already in set");
|
||||
}
|
||||
}
|
||||
void removeShadowDecl(UsingShadowDecl *S) {
|
||||
assert(S->getUsingDecl() == this);
|
||||
if (!Shadows.erase(S)) {
|
||||
assert(false && "declaration not in set");
|
||||
}
|
||||
}
|
||||
|
||||
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
|
||||
SourceLocation UL, NamedDecl* Target,
|
||||
NestedNameSpecifier* TargetNNS, bool IsTypeNameArg);
|
||||
SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL,
|
||||
NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::Using;
|
||||
|
|
|
@ -110,6 +110,7 @@ ABSTRACT_DECL(Named, Decl)
|
|||
DECL(TemplateTemplateParm, TemplateDecl)
|
||||
DECL(Using, NamedDecl)
|
||||
DECL(UnresolvedUsing, NamedDecl)
|
||||
DECL(UsingShadow, NamedDecl)
|
||||
DECL(ObjCMethod, NamedDecl)
|
||||
DECL(ObjCContainer, NamedDecl)
|
||||
DECL(ObjCCategory, ObjCContainerDecl)
|
||||
|
|
|
@ -289,6 +289,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
|
|||
if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD))
|
||||
return true;
|
||||
|
||||
if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD))
|
||||
return cast<UsingShadowDecl>(this)->getTargetDecl() ==
|
||||
cast<UsingShadowDecl>(OldD)->getTargetDecl();
|
||||
|
||||
// For non-function declarations, if the declarations are of the
|
||||
// same kind then this must be a redeclaration, or semantic analysis
|
||||
// would not have given us the new declaration.
|
||||
|
@ -308,7 +312,7 @@ bool NamedDecl::hasLinkage() const {
|
|||
NamedDecl *NamedDecl::getUnderlyingDecl() {
|
||||
NamedDecl *ND = this;
|
||||
while (true) {
|
||||
if (UsingDecl *UD = dyn_cast<UsingDecl>(ND))
|
||||
if (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND))
|
||||
ND = UD->getTargetDecl();
|
||||
else if (ObjCCompatibleAliasDecl *AD
|
||||
= dyn_cast<ObjCCompatibleAliasDecl>(ND))
|
||||
|
|
|
@ -97,7 +97,7 @@ bool Decl::isTemplateParameterPack() const {
|
|||
}
|
||||
|
||||
bool Decl::isFunctionOrFunctionTemplate() const {
|
||||
if (const UsingDecl *UD = dyn_cast<UsingDecl>(this))
|
||||
if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this))
|
||||
return UD->getTargetDecl()->isFunctionOrFunctionTemplate();
|
||||
|
||||
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
|
||||
|
@ -189,10 +189,11 @@ ASTContext &Decl::getASTContext() const {
|
|||
|
||||
unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
switch (DeclKind) {
|
||||
default:
|
||||
if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
|
||||
return IDNS_Ordinary;
|
||||
assert(0 && "Unknown decl kind!");
|
||||
case Function:
|
||||
case CXXMethod:
|
||||
case CXXConstructor:
|
||||
case CXXDestructor:
|
||||
case CXXConversion:
|
||||
case OverloadedFunction:
|
||||
case Typedef:
|
||||
case EnumConstant:
|
||||
|
@ -200,8 +201,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|||
case ImplicitParam:
|
||||
case ParmVar:
|
||||
case NonTypeTemplateParm:
|
||||
case Using:
|
||||
case UnresolvedUsing:
|
||||
case ObjCMethod:
|
||||
case ObjCContainer:
|
||||
case ObjCCategory:
|
||||
|
@ -210,6 +209,15 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|||
case ObjCCompatibleAlias:
|
||||
return IDNS_Ordinary;
|
||||
|
||||
case UsingShadow:
|
||||
return 0; // we'll actually overwrite this later
|
||||
|
||||
case UnresolvedUsing:
|
||||
return IDNS_Tag | IDNS_Ordinary | IDNS_Using;
|
||||
|
||||
case Using:
|
||||
return IDNS_Using;
|
||||
|
||||
case ObjCProtocol:
|
||||
return IDNS_ObjCProtocol;
|
||||
|
||||
|
@ -256,6 +264,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|||
case ClassTemplatePartialSpecialization:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Decl::addAttr(Attr *NewAttr) {
|
||||
|
|
|
@ -914,11 +914,10 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
|
|||
}
|
||||
|
||||
UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
|
||||
SourceLocation UL, NamedDecl* Target,
|
||||
NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) {
|
||||
return new (C) UsingDecl(DC, L, NNR, TargetNL, UL, Target,
|
||||
TargetNNS, IsTypeNameArg);
|
||||
SourceLocation L, SourceRange NNR, SourceLocation UL,
|
||||
NestedNameSpecifier* TargetNNS, DeclarationName Name,
|
||||
bool IsTypeNameArg) {
|
||||
return new (C) UsingDecl(DC, L, NNR, UL, TargetNNS, Name, IsTypeNameArg);
|
||||
}
|
||||
|
||||
UnresolvedUsingDecl *UnresolvedUsingDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace {
|
|||
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
|
||||
void VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
|
||||
void VisitUsingDecl(UsingDecl *D);
|
||||
void VisitUsingShadowDecl(UsingShadowDecl *D);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -825,7 +826,7 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
|
|||
void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
|
||||
Out << "using ";
|
||||
D->getTargetNestedNameDecl()->print(Out, Policy);
|
||||
Out << D->getTargetDecl()->getNameAsString();
|
||||
Out << D->getNameAsString();
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
|
||||
|
@ -833,3 +834,7 @@ void DeclPrinter::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
|
|||
D->getTargetNestedNameSpecifier()->print(Out, Policy);
|
||||
Out << D->getTargetName().getAsString();
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
|
||||
// ignore
|
||||
}
|
||||
|
|
|
@ -1197,6 +1197,7 @@ public:
|
|||
LookupKind(LookupKind),
|
||||
IDNS(0),
|
||||
Redecl(Redecl != NotForRedeclaration),
|
||||
HideTags(true),
|
||||
Diagnose(Redecl == NotForRedeclaration)
|
||||
{}
|
||||
|
||||
|
@ -1212,6 +1213,7 @@ public:
|
|||
LookupKind(Other.LookupKind),
|
||||
IDNS(Other.IDNS),
|
||||
Redecl(Other.Redecl),
|
||||
HideTags(Other.HideTags),
|
||||
Diagnose(false)
|
||||
{}
|
||||
|
||||
|
@ -1235,6 +1237,12 @@ public:
|
|||
return Redecl;
|
||||
}
|
||||
|
||||
/// Sets whether tag declarations should be hidden by non-tag
|
||||
/// declarations during resolution. The default is true.
|
||||
void setHideTags(bool Hide) {
|
||||
HideTags = Hide;
|
||||
}
|
||||
|
||||
/// The identifier namespace of this lookup. This information is
|
||||
/// private to the lookup routines.
|
||||
unsigned getIdentifierNamespace() const {
|
||||
|
@ -1441,6 +1449,10 @@ public:
|
|||
unsigned IDNS; // ill-defined until set by lookup
|
||||
bool Redecl;
|
||||
|
||||
/// \brief True if tag declarations should be hidden if non-tags
|
||||
/// are present
|
||||
bool HideTags;
|
||||
|
||||
bool Diagnose;
|
||||
};
|
||||
|
||||
|
@ -2007,7 +2019,8 @@ public:
|
|||
SourceLocation IdentLoc,
|
||||
IdentifierInfo *Ident);
|
||||
|
||||
NamedDecl *BuildUsingDeclaration(SourceLocation UsingLoc,
|
||||
NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
|
||||
SourceLocation UsingLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
SourceLocation IdentLoc,
|
||||
DeclarationName Name,
|
||||
|
|
|
@ -198,7 +198,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
|
|||
return;
|
||||
|
||||
// Look through using declarations.
|
||||
if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration))
|
||||
if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration))
|
||||
MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier),
|
||||
CurContext);
|
||||
|
||||
|
|
|
@ -2835,7 +2835,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
|
|||
}
|
||||
|
||||
DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
|
||||
NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS,
|
||||
NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
|
||||
Name.getSourceRange().getBegin(),
|
||||
TargetName, AttrList, IsTypeName);
|
||||
if (UD) {
|
||||
|
@ -2846,7 +2846,34 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
|
|||
return DeclPtrTy::make(UD);
|
||||
}
|
||||
|
||||
NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
|
||||
/// Builds a shadow declaration corresponding to a 'using' declaration.
|
||||
static UsingShadowDecl *BuildUsingShadowDecl(Sema &SemaRef, Scope *S,
|
||||
AccessSpecifier AS,
|
||||
UsingDecl *UD, NamedDecl *Orig) {
|
||||
// FIXME: diagnose hiding, collisions
|
||||
|
||||
// If we resolved to another shadow declaration, just coalesce them.
|
||||
if (isa<UsingShadowDecl>(Orig)) {
|
||||
Orig = cast<UsingShadowDecl>(Orig)->getTargetDecl();
|
||||
assert(!isa<UsingShadowDecl>(Orig) && "nested shadow declaration");
|
||||
}
|
||||
|
||||
UsingShadowDecl *Shadow
|
||||
= UsingShadowDecl::Create(SemaRef.Context, SemaRef.CurContext,
|
||||
UD->getLocation(), UD, Orig);
|
||||
UD->addShadowDecl(Shadow);
|
||||
|
||||
if (S)
|
||||
SemaRef.PushOnScopeChains(Shadow, S);
|
||||
else
|
||||
SemaRef.CurContext->addDecl(Shadow);
|
||||
Shadow->setAccess(AS);
|
||||
|
||||
return Shadow;
|
||||
}
|
||||
|
||||
NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
|
||||
SourceLocation UsingLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
SourceLocation IdentLoc,
|
||||
DeclarationName Name,
|
||||
|
@ -2880,7 +2907,7 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
|
|||
// anonymous union that is a member of a base class of the class being
|
||||
// defined, or shall refer to an enumerator for an enumeration type that is
|
||||
// a member of a base class of the class being defined.
|
||||
|
||||
|
||||
CXXRecordDecl *LookupRD = dyn_cast<CXXRecordDecl>(LookupContext);
|
||||
if (!LookupRD || !RD->isDerivedFrom(LookupRD)) {
|
||||
Diag(SS.getRange().getBegin(),
|
||||
|
@ -2898,8 +2925,12 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
|
|||
}
|
||||
}
|
||||
|
||||
// Lookup target name.
|
||||
// Look up the target name. Unlike most lookups, we do not want to
|
||||
// hide tag declarations: tag names are visible through the using
|
||||
// declaration even if hidden by ordinary names.
|
||||
LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName);
|
||||
R.setHideTags(false);
|
||||
|
||||
LookupQualifiedName(R, LookupContext);
|
||||
|
||||
if (R.empty()) {
|
||||
|
@ -2908,24 +2939,33 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: handle ambiguity?
|
||||
NamedDecl *ND = R.getAsSingleDecl(Context);
|
||||
if (R.isAmbiguous())
|
||||
return 0;
|
||||
|
||||
if (IsTypeName && !isa<TypeDecl>(ND)) {
|
||||
if (IsTypeName &&
|
||||
(R.getResultKind() != LookupResult::Found
|
||||
|| !isa<TypeDecl>(R.getFoundDecl()))) {
|
||||
Diag(IdentLoc, diag::err_using_typename_non_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// C++0x N2914 [namespace.udecl]p6:
|
||||
// A using-declaration shall not name a namespace.
|
||||
if (isa<NamespaceDecl>(ND)) {
|
||||
if (R.getResultKind() == LookupResult::Found
|
||||
&& isa<NamespaceDecl>(R.getFoundDecl())) {
|
||||
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
|
||||
<< SS.getRange();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(),
|
||||
ND->getLocation(), UsingLoc, ND, NNS, IsTypeName);
|
||||
UsingDecl *UD = UsingDecl::Create(Context, CurContext, IdentLoc,
|
||||
SS.getRange(), UsingLoc, NNS, Name,
|
||||
IsTypeName);
|
||||
|
||||
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
|
||||
BuildUsingShadowDecl(*this, S, AS, UD, *I);
|
||||
|
||||
return UD;
|
||||
}
|
||||
|
||||
/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
|
||||
|
|
|
@ -297,7 +297,7 @@ void Sema::LookupResult::resolveKind() {
|
|||
// wherever the object, function, or enumerator name is visible.
|
||||
// But it's still an error if there are distinct tag types found,
|
||||
// even if they're not visible. (ref?)
|
||||
if (HasTag && !Ambiguous && (HasFunction || HasNonFunction))
|
||||
if (HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction))
|
||||
Decls[UniqueTagIndex] = Decls[--N];
|
||||
|
||||
Decls.set_size(N);
|
||||
|
|
|
@ -788,10 +788,46 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
|
|||
if (!InstD)
|
||||
return SemaRef.ExprError();
|
||||
|
||||
// If we instantiated an UnresolvedUsingDecl and got back an UsingDecl,
|
||||
// we need to get the underlying decl.
|
||||
// FIXME: Is this correct? Maybe FindInstantiatedDecl should do this?
|
||||
InstD = InstD->getUnderlyingDecl();
|
||||
// Flatten using declarations into their shadow declarations.
|
||||
if (isa<UsingDecl>(InstD)) {
|
||||
UsingDecl *UD = cast<UsingDecl>(InstD);
|
||||
|
||||
bool HasNonFunction = false;
|
||||
|
||||
llvm::SmallVector<NamedDecl*, 8> Decls;
|
||||
for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
|
||||
E = UD->shadow_end(); I != E; ++I) {
|
||||
NamedDecl *TD = (*I)->getTargetDecl();
|
||||
if (!TD->isFunctionOrFunctionTemplate())
|
||||
HasNonFunction = true;
|
||||
|
||||
Decls.push_back(TD);
|
||||
}
|
||||
|
||||
if (Decls.empty())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
if (Decls.size() == 1)
|
||||
InstD = Decls[0];
|
||||
else if (!HasNonFunction) {
|
||||
OverloadedFunctionDecl *OFD
|
||||
= OverloadedFunctionDecl::Create(SemaRef.Context,
|
||||
UD->getDeclContext(),
|
||||
UD->getDeclName());
|
||||
for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Decls.begin(),
|
||||
E = Decls.end(); I != E; ++I)
|
||||
if (isa<FunctionDecl>(*I))
|
||||
OFD->addOverload(cast<FunctionDecl>(*I));
|
||||
else
|
||||
OFD->addOverload(cast<FunctionTemplateDecl>(*I));
|
||||
|
||||
InstD = OFD;
|
||||
} else {
|
||||
// FIXME
|
||||
assert(false && "using declaration resolved to mixed set");
|
||||
return SemaRef.ExprError();
|
||||
}
|
||||
}
|
||||
|
||||
CXXScopeSpec SS;
|
||||
NestedNameSpecifier *Qualifier = 0;
|
||||
|
|
|
@ -1019,9 +1019,9 @@ TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
|
|||
SS.setScopeRep(NNS);
|
||||
|
||||
NamedDecl *UD =
|
||||
SemaRef.BuildUsingDeclaration(D->getLocation(), SS,
|
||||
D->getTargetNameLocation(),
|
||||
D->getTargetName(), 0, D->isTypeName());
|
||||
SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
|
||||
D->getLocation(), SS, D->getTargetNameLocation(),
|
||||
D->getDeclName(), 0, D->isTypeName());
|
||||
if (UD)
|
||||
SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
|
||||
D);
|
||||
|
|
Loading…
Reference in New Issue