aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-12-04 22:46:56 +0000
committerJohn McCall <rjmccall@apple.com>2009-12-04 22:46:56 +0000
commited97649e9574b9d854fa4d6109c9333ae0993554 (patch)
tree799328f967a0d6af2b9dbdd5c2df4a8392275680
parentcce9fde82ad99cb96c820084d636c9bfdfcff30a (diff)
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
-rw-r--r--include/clang/AST/ASTContext.h27
-rw-r--r--include/clang/AST/Type.h33
-rw-r--r--include/clang/AST/TypeLoc.h155
-rw-r--r--include/clang/AST/TypeLocBuilder.h45
-rw-r--r--include/clang/AST/TypeNodes.def1
-rw-r--r--include/clang/Frontend/PCHBitCodes.h4
-rw-r--r--lib/AST/ASTContext.cpp41
-rw-r--r--lib/AST/TypeLoc.cpp29
-rw-r--r--lib/AST/TypePrinter.cpp9
-rw-r--r--lib/CodeGen/Mangle.cpp6
-rw-r--r--lib/Frontend/PCHReader.cpp7
-rw-r--r--lib/Frontend/PCHWriter.cpp11
-rw-r--r--lib/Sema/Sema.h4
-rw-r--r--lib/Sema/SemaDeclCXX.cpp83
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp1
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp2
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp84
-rw-r--r--lib/Sema/TreeTransform.h51
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp183
-rw-r--r--test/SemaCXX/using-decl-templates.cpp11
20 files changed, 670 insertions, 117 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 6efb634a8c..78ead42007 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -57,6 +57,7 @@ namespace clang {
class TypeDecl;
class TypedefDecl;
class UsingDecl;
+ class UsingShadowDecl;
namespace Builtin { class Context; }
@@ -183,8 +184,10 @@ class ASTContext {
llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>
InstantiatedFromStaticDataMember;
- /// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls
- /// where created during instantiation.
+ /// \brief Keeps track of the declaration from which a UsingDecl was
+ /// created during instantiation. The source declaration is always
+ /// a UsingDecl, an UnresolvedUsingValueDecl, or an
+ /// UnresolvedUsingTypenameDecl.
///
/// For example:
/// \code
@@ -203,8 +206,10 @@ class ASTContext {
///
/// This mapping will contain an entry that maps from the UsingDecl in
/// B<int> to the UnresolvedUsingDecl in B<T>.
- llvm::DenseMap<UsingDecl *, NamedDecl *>
- InstantiatedFromUnresolvedUsingDecl;
+ llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUsingDecl;
+
+ llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>
+ InstantiatedFromUsingShadowDecl;
llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
@@ -282,14 +287,18 @@ public:
void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
TemplateSpecializationKind TSK);
- /// \brief If this using decl is instantiated from an unresolved using decl,
+ /// \brief If the given using decl is an instantiation of a
+ /// (possibly unresolved) using decl from a template instantiation,
/// return it.
- NamedDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD);
+ NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst);
- /// \brief Note that the using decl \p Inst is an instantiation of
- /// the unresolved using decl \p Tmpl of a class template.
- void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl);
+ /// \brief Remember that the using decl \p Inst is an instantiation
+ /// of the using decl \p Pattern of a class template.
+ void setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern);
+ void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
+ UsingShadowDecl *Pattern);
+ UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst);
FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field);
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 16b6dd7215..7b5598c460 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -76,6 +76,7 @@ namespace clang {
class ObjCInterfaceDecl;
class ObjCProtocolDecl;
class ObjCMethodDecl;
+ class UnresolvedUsingTypenameDecl;
class Expr;
class Stmt;
class SourceLocation;
@@ -1863,6 +1864,38 @@ public:
};
+/// \brief Represents the dependent type named by a dependently-scoped
+/// typename using declaration, e.g.
+/// using typename Base<T>::foo;
+/// Template instantiation turns these into the underlying type.
+class UnresolvedUsingType : public Type {
+ UnresolvedUsingTypenameDecl *Decl;
+
+ UnresolvedUsingType(UnresolvedUsingTypenameDecl *D)
+ : Type(UnresolvedUsing, QualType(), true), Decl(D) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ UnresolvedUsingTypenameDecl *getDecl() const { return Decl; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == UnresolvedUsing;
+ }
+ static bool classof(const UnresolvedUsingType *) { return true; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ return Profile(ID, Decl);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ UnresolvedUsingTypenameDecl *D) {
+ ID.AddPointer(D);
+ }
+};
+
+
class TypedefType : public Type {
TypedefDecl *Decl;
protected:
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index f08ca6bf46..47274450b1 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -340,16 +340,20 @@ public:
}
};
+
struct TypeSpecLocInfo {
SourceLocation NameLoc;
};
/// \brief A reasonable base class for TypeLocs that correspond to
/// types that are written as a type-specifier.
-template <class Derived, class TypeClass, class LocalData = TypeSpecLocInfo>
-class TypeSpecTypeLoc
- : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {
+class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ TypeSpecTypeLoc,
+ Type,
+ TypeSpecLocInfo> {
public:
+ enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
+
SourceLocation getNameLoc() const {
return this->getLocalData()->NameLoc;
}
@@ -362,31 +366,79 @@ public:
void initializeLocal(SourceLocation Loc) {
setNameLoc(Loc);
}
+
+ static bool classof(const TypeLoc *TL);
+ static bool classof(const TypeSpecTypeLoc *TL) { return true; }
};
+
/// \brief Wrapper for source info for typedefs.
-class TypedefTypeLoc : public TypeSpecTypeLoc<TypedefTypeLoc,TypedefType> {
+class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TypedefTypeLoc,
+ TypedefType> {
public:
TypedefDecl *getTypedefDecl() const {
return getTypePtr()->getDecl();
}
};
+/// \brief Wrapper for source info for unresolved typename using decls.
+class UnresolvedUsingTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ UnresolvedUsingTypeLoc,
+ UnresolvedUsingType> {
+public:
+ UnresolvedUsingTypenameDecl *getDecl() const {
+ return getTypePtr()->getDecl();
+ }
+};
+
+/// \brief Wrapper for source info for tag types. Note that this only
+/// records source info for the name itself; a type written 'struct foo'
+/// should be represented as an ElaboratedTypeLoc. We currently
+/// only do that when C++ is enabled because of the expense of
+/// creating an ElaboratedType node for so many type references in C.
+class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TagTypeLoc,
+ TagType> {
+public:
+ TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
+};
+
+/// \brief Wrapper for source info for record types.
+class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
+ RecordTypeLoc,
+ RecordType> {
+public:
+ RecordDecl *getDecl() const { return getTypePtr()->getDecl(); }
+};
+
+/// \brief Wrapper for source info for enum types.
+class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
+ EnumTypeLoc,
+ EnumType> {
+public:
+ EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
+};
/// \brief Wrapper for source info for builtin types.
-class BuiltinTypeLoc : public TypeSpecTypeLoc<BuiltinTypeLoc,
- BuiltinType> {
+class BuiltinTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ BuiltinTypeLoc,
+ BuiltinType> {
};
/// \brief Wrapper for template type parameters.
-class TemplateTypeParmTypeLoc : public TypeSpecTypeLoc<TemplateTypeParmTypeLoc,
- TemplateTypeParmType> {
+class TemplateTypeParmTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TemplateTypeParmTypeLoc,
+ TemplateTypeParmType> {
};
/// \brief Wrapper for substituted template type parameters.
class SubstTemplateTypeParmTypeLoc :
- public TypeSpecTypeLoc<SubstTemplateTypeParmTypeLoc,
- SubstTemplateTypeParmType> {
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ SubstTemplateTypeParmTypeLoc,
+ SubstTemplateTypeParmType> {
};
@@ -944,63 +996,84 @@ private:
}
};
-// None of these types have proper implementations yet.
+//===----------------------------------------------------------------------===//
+//
+// All of these need proper implementations.
+//
+//===----------------------------------------------------------------------===//
-class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> {
+// FIXME: size expression and attribute locations (or keyword if we
+// ever fully support altivec syntax).
+class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ VectorTypeLoc,
+ VectorType> {
};
+// FIXME: size expression and attribute locations.
class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
ExtVectorTypeLoc,
ExtVectorType> {
};
+// FIXME: attribute locations.
// For some reason, this isn't a subtype of VectorType.
class DependentSizedExtVectorTypeLoc :
- public TypeSpecTypeLoc<DependentSizedExtVectorTypeLoc,
- DependentSizedExtVectorType> {
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ DependentSizedExtVectorTypeLoc,
+ DependentSizedExtVectorType> {
};
-class FixedWidthIntTypeLoc : public TypeSpecTypeLoc<FixedWidthIntTypeLoc,
- FixedWidthIntType> {
+// FIXME: I'm not sure how you actually specify these; with attributes?
+class FixedWidthIntTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ FixedWidthIntTypeLoc,
+ FixedWidthIntType> {
};
-class ComplexTypeLoc : public TypeSpecTypeLoc<ComplexTypeLoc,
- ComplexType> {
+// FIXME: location of the '_Complex' keyword.
+class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ ComplexTypeLoc,
+ ComplexType> {
};
-class TypeOfExprTypeLoc : public TypeSpecTypeLoc<TypeOfExprTypeLoc,
- TypeOfExprType> {
+// FIXME: location of the 'typeof' and parens (the expression is
+// carried by the type).
+class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TypeOfExprTypeLoc,
+ TypeOfExprType> {
};
-class TypeOfTypeLoc : public TypeSpecTypeLoc<TypeOfTypeLoc, TypeOfType> {
+// FIXME: location of the 'typeof' and parens; also the DeclaratorInfo
+// for the inner type, or (maybe) just express that inline to the TypeLoc.
+class TypeOfTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TypeOfTypeLoc,
+ TypeOfType> {
};
-class DecltypeTypeLoc : public TypeSpecTypeLoc<DecltypeTypeLoc, DecltypeType> {
-};
-
-class TagTypeLoc : public TypeSpecTypeLoc<TagTypeLoc, TagType> {
-};
-
-class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
- RecordTypeLoc,
- RecordType> {
-};
-
-class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
- EnumTypeLoc,
- EnumType> {
+// FIXME: location of the 'decltype' and parens.
+class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ DecltypeTypeLoc,
+ DecltypeType> {
};
-class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc,
- ElaboratedType> {
+// FIXME: location of the tag keyword.
+class ElaboratedTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ ElaboratedTypeLoc,
+ ElaboratedType> {
};
-class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc,
- QualifiedNameType> {
+// FIXME: locations for the nested name specifier; at the very least,
+// a SourceRange.
+class QualifiedNameTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ QualifiedNameTypeLoc,
+ QualifiedNameType> {
};
-class TypenameTypeLoc : public TypeSpecTypeLoc<TypenameTypeLoc,
- TypenameType> {
+// FIXME: locations for the typename keyword and nested name specifier.
+class TypenameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TypenameTypeLoc,
+ TypenameType> {
};
}
diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h
index 00e2b7f832..f4263c3de3 100644
--- a/include/clang/AST/TypeLocBuilder.h
+++ b/include/clang/AST/TypeLocBuilder.h
@@ -59,9 +59,35 @@ class TypeLocBuilder {
grow(Requested);
}
- /// Pushes space for a new TypeLoc onto the given type. Invalidates
+ /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
+ /// previously retrieved from this builder.
+ TypeSpecTypeLoc pushTypeSpec(QualType T) {
+ size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
+ return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
+ }
+
+
+ /// Pushes space for a new TypeLoc of the given type. Invalidates
/// any TypeLocs previously retrieved from this builder.
template <class TyLocType> TyLocType push(QualType T) {
+ size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
+ return cast<TyLocType>(pushImpl(T, LocalSize));
+ }
+
+ /// Creates a DeclaratorInfo for the given type.
+ DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) {
+#ifndef NDEBUG
+ assert(T == LastTy && "type doesn't match last type pushed!");
+#endif
+
+ size_t FullDataSize = Capacity - Index;
+ DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize);
+ memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
+ return DI;
+ }
+
+private:
+ TypeLoc pushImpl(QualType T, size_t LocalSize) {
#ifndef NDEBUG
QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
assert(TLast == LastTy &&
@@ -69,8 +95,6 @@ class TypeLocBuilder {
LastTy = T;
#endif
- size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
-
// If we need to grow, grow by a factor of 2.
if (LocalSize > Index) {
size_t RequiredCapacity = Capacity + (LocalSize - Index);
@@ -82,22 +106,9 @@ class TypeLocBuilder {
Index -= LocalSize;
- return cast<TyLocType>(TypeLoc(T, &Buffer[Index]));
- }
-
- /// Creates a DeclaratorInfo for the given type.
- DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) {
-#ifndef NDEBUG
- assert(T == LastTy && "type doesn't match last type pushed!");
-#endif
-
- size_t FullDataSize = Capacity - Index;
- DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize);
- memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
- return DI;
+ return TypeLoc(T, &Buffer[Index]);
}
- private:
/// Grow to the given capacity.
void grow(size_t NewCapacity) {
assert(NewCapacity > Capacity);
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index c2721236af..b9d37992a6 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -71,6 +71,7 @@ TYPE(ExtVector, VectorType)
ABSTRACT_TYPE(Function, Type)
TYPE(FunctionProto, FunctionType)
TYPE(FunctionNoProto, FunctionType)
+DEPENDENT_TYPE(UnresolvedUsing, Type)
NON_CANONICAL_TYPE(Typedef, Type)
NON_CANONICAL_TYPE(TypeOfExpr, Type)
NON_CANONICAL_TYPE(TypeOf, Type)
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
index 98463c308e..c8c49c83f9 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -404,7 +404,9 @@ namespace clang {
/// \brief An ElaboratedType record.
TYPE_ELABORATED = 24,
/// \brief A SubstTemplateTypeParmType record.
- TYPE_SUBST_TEMPLATE_TYPE_PARM = 25
+ TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
+ /// \brief An UnresolvedUsingType record.
+ TYPE_UNRESOLVED_USING = 26
};
/// \brief The type IDs for special types constructed by semantic
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index a63db14a0f..94f2fdcff9 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -260,24 +260,40 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
}
NamedDecl *
-ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
+ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
- = InstantiatedFromUnresolvedUsingDecl.find(UUD);
- if (Pos == InstantiatedFromUnresolvedUsingDecl.end())
+ = InstantiatedFromUsingDecl.find(UUD);
+ if (Pos == InstantiatedFromUsingDecl.end())
return 0;
return Pos->second;
}
void
-ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD,
- NamedDecl *UUD) {
- assert((isa<UnresolvedUsingValueDecl>(UUD) ||
- isa<UnresolvedUsingTypenameDecl>(UUD)) &&
- "original declaration is not an unresolved using decl");
- assert(!InstantiatedFromUnresolvedUsingDecl[UD] &&
- "Already noted what using decl what instantiated from");
- InstantiatedFromUnresolvedUsingDecl[UD] = UUD;
+ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) {
+ assert((isa<UsingDecl>(Pattern) ||
+ isa<UnresolvedUsingValueDecl>(Pattern) ||
+ isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
+ "pattern decl is not a using decl");
+ assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
+ InstantiatedFromUsingDecl[Inst] = Pattern;
+}
+
+UsingShadowDecl *
+ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) {
+ llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos
+ = InstantiatedFromUsingShadowDecl.find(Inst);
+ if (Pos == InstantiatedFromUsingShadowDecl.end())
+ return 0;
+
+ return Pos->second;
+}
+
+void
+ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
+ UsingShadowDecl *Pattern) {
+ assert(!InstantiatedFromUsingShadowDecl[Inst] && "pattern already exists");
+ InstantiatedFromUsingShadowDecl[Inst] = Pattern;
}
FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) {
@@ -1766,6 +1782,9 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) {
Decl->TypeForDecl = PrevDecl->TypeForDecl;
else
Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum);
+ } else if (UnresolvedUsingTypenameDecl *Using =
+ dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
+ Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using);
} else
assert(false && "TypeDecl without a type?");
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 50a512028e..3ccb7a9cc6 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -94,3 +94,32 @@ void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) {
TypeLocInitializer(Loc).Visit(TL);
} while ((TL = TL.getNextTypeLoc()));
}
+
+namespace {
+ struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
+ // Overload resolution does the real work for us.
+ static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
+ static bool isTypeSpec(TypeLoc _) { return false; }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return isTypeSpec(TyLoc); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+
+/// \brief Determines if the given type loc corresponds to a
+/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
+/// the type hierarchy, this is made somewhat complicated.
+///
+/// There are a lot of types that currently use TypeSpecTypeLoc
+/// because it's a convenient base class. Ideally we would not accept
+/// those here, but ideally we would have better implementations for
+/// them.
+bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
+ if (TL->getType().hasLocalQualifiers()) return false;
+ return TSTChecker().Visit(*TL);
+}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 3d7a5376d7..2f58ebed4b 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -303,6 +303,15 @@ void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
Print(T->getResultType(), S);
}
+void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
+ std::string &S) {
+ IdentifierInfo *II = T->getDecl()->getIdentifier();
+ if (S.empty())
+ S = II->getName().str();
+ else
+ S = II->getName().str() + ' ' + S;
+}
+
void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
S = ' ' + S;
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 4d021e8964..df708eda9c 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -843,6 +843,12 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
// <type> ::= <class-enum-type>
// <class-enum-type> ::= <name>
+void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {
+ mangleName(T->getDecl());
+}
+
+// <type> ::= <class-enum-type>
+// <class-enum-type> ::= <name>
void CXXNameMangler::mangleType(const EnumType *T) {
mangleType(static_cast<const TagType*>(T));
}
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 40eb9ca536..811f9ed4af 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1880,6 +1880,10 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Exceptions.data());
}
+ case pch::TYPE_UNRESOLVED_USING:
+ return Context->getTypeDeclType(
+ cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0])));
+
case pch::TYPE_TYPEDEF:
assert(Record.size() == 1 && "incorrect encoding of typedef type");
return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
@@ -2044,6 +2048,9 @@ void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index e79f9c9dac..0e6d1d2f66 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -166,6 +166,14 @@ void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
Code = pch::TYPE_FUNCTION_PROTO;
}
+#if 0
+// For when we want it....
+void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ Code = pch::TYPE_UNRESOLVED_USING;
+}
+#endif
+
void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
Code = pch::TYPE_TYPEDEF;
@@ -337,6 +345,9 @@ void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 616151efea..9606821f78 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1729,6 +1729,10 @@ public:
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 58b5633afa..992bb80189 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2900,10 +2900,8 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
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 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
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 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
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 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
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 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
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. Otherwi