Fix "using typename" and the instantiation of non-dependent using declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90614 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 616151e..9606821 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1729,6 +1729,10 @@
SourceLocation IdentLoc,
IdentifierInfo *Ident);
+ bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc);
+
NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 58b5633..992bb80 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2900,10 +2900,8 @@
TargetName, AttrList,
/* IsInstantiation */ false,
IsTypeName, TypenameLoc);
- if (UD) {
- PushOnScopeChains(UD, S);
- UD->setAccess(AS);
- }
+ if (UD)
+ PushOnScopeChains(UD, S, /*AddToContext*/ false);
return DeclPtrTy::make(UD);
}
@@ -2962,19 +2960,33 @@
NestedNameSpecifier *NNS =
static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
+ return 0;
+
DeclContext *LookupContext = computeDeclContext(SS);
+ NamedDecl *D;
if (!LookupContext) {
if (IsTypeName) {
- return UnresolvedUsingTypenameDecl::Create(Context, CurContext,
- UsingLoc, TypenameLoc,
- SS.getRange(), NNS,
- IdentLoc, Name);
- } else {
- return UnresolvedUsingValueDecl::Create(Context, CurContext,
- UsingLoc, SS.getRange(), NNS,
+ // FIXME: not all declaration name kinds are legal here
+ D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+ UsingLoc, TypenameLoc,
+ SS.getRange(), NNS,
IdentLoc, Name);
+ } else {
+ D = UnresolvedUsingValueDecl::Create(Context, CurContext,
+ UsingLoc, SS.getRange(), NNS,
+ IdentLoc, Name);
}
+ } else {
+ D = UsingDecl::Create(Context, CurContext, IdentLoc,
+ SS.getRange(), UsingLoc, NNS, Name,
+ IsTypeName);
}
+ D->setAccess(AS);
+ CurContext->addDecl(D);
+
+ if (!LookupContext) return D;
+ UsingDecl *UD = cast<UsingDecl>(D);
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
// C++0x N2914 [namespace.udecl]p3:
@@ -2989,7 +3001,8 @@
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_a_base_class)
<< NNS << RD->getDeclName();
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
} else {
// C++0x N2914 [namespace.udecl]p8:
@@ -2997,7 +3010,8 @@
if (isa<CXXRecordDecl>(LookupContext)) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member)
<< SS.getRange();
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
}
@@ -3017,54 +3031,63 @@
if (R.empty()) {
Diag(IdentLoc, diag::err_no_member)
<< Name << LookupContext << SS.getRange();
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
- if (R.isAmbiguous())
- return 0;
+ if (R.isAmbiguous()) {
+ UD->setInvalidDecl();
+ return UD;
+ }
if (IsTypeName) {
// If we asked for a typename and got a non-type decl, error out.
- if (R.getResultKind() != LookupResult::Found
- || !isa<TypeDecl>(R.getFoundDecl())) {
+ if (!R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_typename_non_type);
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
Diag((*I)->getUnderlyingDecl()->getLocation(),
diag::note_using_decl_target);
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
} else {
// If we asked for a non-typename and we got a type, error out,
// but only if this is an instantiation of an unresolved using
// decl. Otherwise just silently find the type name.
- if (IsInstantiation &&
- R.getResultKind() == LookupResult::Found &&
- isa<TypeDecl>(R.getFoundDecl())) {
+ if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_dependent_value_is_type);
Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
}
// C++0x N2914 [namespace.udecl]p6:
// A using-declaration shall not name a namespace.
- if (R.getResultKind() == LookupResult::Found
- && isa<NamespaceDecl>(R.getFoundDecl())) {
+ if (R.getAsSingle<NamespaceDecl>()) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
<< SS.getRange();
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
- 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;
}
+/// Checks that the given nested-name qualifier used in a using decl
+/// in the current context is appropriately related to the current
+/// scope. If an error is found, diagnoses it and returns true.
+bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc) {
+ // FIXME: implement
+
+ return false;
+}
+
Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 613ffde..b4754db 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2361,6 +2361,7 @@
case Type::Enum:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::UnresolvedUsing:
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 122e85e..6a4ac3c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1064,8 +1064,6 @@
Invalid = true;
} else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
Fields.push_back(DeclPtrTy::make(Field));
- else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember))
- Instantiation->addDecl(UD);
} else {
// FIXME: Eventually, a NULL return will mean that one of the
// instantiations was a semantic disaster, and we'll want to set Invalid =
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ec28f47..6b41d9a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -66,6 +66,8 @@
Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ Decl *VisitUsingDecl(UsingDecl *D);
+ Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
@@ -1034,6 +1036,56 @@
return Inst;
}
+Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
+ // The nested name specifier is non-dependent, so no transformation
+ // is required.
+
+ UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
+ D->getLocation(),
+ D->getNestedNameRange(),
+ D->getUsingLocation(),
+ D->getTargetNestedNameDecl(),
+ D->getDeclName(),
+ D->isTypeName());
+
+ CXXScopeSpec SS;
+ SS.setScopeRep(D->getTargetNestedNameDecl());
+ SS.setRange(D->getNestedNameRange());
+ if (SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+ D->getLocation()))
+ NewUD->setInvalidDecl();
+ SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
+ NewUD->setAccess(D->getAccess());
+ Owner->addDecl(NewUD);
+
+ // We'll transform the UsingShadowDecls as we reach them.
+
+ return NewUD;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ UsingDecl *InstUsing =
+ cast<UsingDecl>(SemaRef.FindInstantiatedDecl(D->getUsingDecl(),
+ TemplateArgs));
+ NamedDecl *InstTarget =
+ cast<NamedDecl>(SemaRef.FindInstantiatedDecl(D->getTargetDecl(),
+ TemplateArgs));
+
+ UsingShadowDecl *InstD = UsingShadowDecl::Create(SemaRef.Context, Owner,
+ InstUsing->getLocation(),
+ InstUsing, InstTarget);
+ InstUsing->addShadowDecl(InstD);
+
+ if (InstTarget->isInvalidDecl() || InstUsing->isInvalidDecl())
+ InstD->setInvalidDecl();
+
+ SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstD, D);
+ InstD->setAccess(D->getAccess());
+ Owner->addDecl(InstD);
+
+ return InstD;
+}
+
Decl * TemplateDeclInstantiator
::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
NestedNameSpecifier *NNS =
@@ -1054,8 +1106,8 @@
/*instantiation*/ true,
/*typename*/ true, D->getTypenameLoc());
if (UD)
- SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
- D);
+ SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
return UD;
}
@@ -1079,8 +1131,8 @@
/*instantiation*/ true,
/*typename*/ false, SourceLocation());
if (UD)
- SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
- D);
+ SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
return UD;
}
@@ -1753,16 +1805,28 @@
return false;
}
+static bool isInstantiationOf(UsingShadowDecl *Pattern,
+ UsingShadowDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UsingDecl *Pattern,
+ UsingDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
UsingDecl *Instance,
ASTContext &C) {
- return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
}
static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
UsingDecl *Instance,
ASTContext &C) {
- return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
}
static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
@@ -1780,6 +1844,8 @@
return false;
}
+// Other is the prospective instantiation
+// D is the prospective pattern
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
if (D->getKind() != Other->getKind()) {
if (UnresolvedUsingTypenameDecl *UUD
@@ -1831,6 +1897,12 @@
}
}
+ if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
+ return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
+
+ if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
+ return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
+
return D->getDeclName() && isa<NamedDecl>(Other) &&
D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index e1ac322..b029a37 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -461,6 +461,10 @@
/// \brief Build a new unprototyped function type.
QualType RebuildFunctionNoProtoType(QualType ResultType);
+ /// \brief Rebuild an unresolved typename type, given the decl that
+ /// the UnresolvedUsingTypenameDecl was transformed to.
+ QualType RebuildUnresolvedUsingType(Decl *D);
+
/// \brief Build a new typedef type.
QualType RebuildTypedefType(TypedefDecl *Typedef) {
return SemaRef.Context.getTypeDeclType(Typedef);
@@ -2578,6 +2582,29 @@
return Result;
}
+template<typename Derived> QualType
+TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
+ UnresolvedUsingTypeLoc TL) {
+ UnresolvedUsingType *T = TL.getTypePtr();
+ Decl *D = getDerived().TransformDecl(T->getDecl());
+ if (!D)
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
+ Result = getDerived().RebuildUnresolvedUsingType(D);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // We might get an arbitrary type spec type back. We should at
+ // least always get a type spec type, though.
+ TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
TypedefTypeLoc TL) {
@@ -5318,6 +5345,30 @@
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
+ assert(D && "no decl found");
+ if (D->isInvalidDecl()) return QualType();
+
+ TypeDecl *Ty;
+ if (isa<UsingDecl>(D)) {
+ UsingDecl *Using = cast<UsingDecl>(D);
+ assert(Using->isTypeName() &&
+ "UnresolvedUsingTypenameDecl transformed to non-typename using");
+
+ // A valid resolved using typename decl points to exactly one type decl.
+ assert(++Using->shadow_begin() == Using->shadow_end());
+ Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
+
+ } else {
+ assert(isa<UnresolvedUsingTypenameDecl>(D) &&
+ "UnresolvedUsingTypenameDecl transformed to non-using decl");
+ Ty = cast<UnresolvedUsingTypenameDecl>(D);
+ }
+
+ return SemaRef.Context.getTypeDeclType(Ty);
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
}