[cfe-commits] r90614 - in /cfe/trunk: include/clang/AST/ include/clang/Frontend/ lib/AST/ lib/CodeGen/ lib/Frontend/ lib/Sema/ test/CXX/dcl.dcl/basic.namespace/namespace.udecl/ test/SemaCXX/
John McCall
rjmccall at apple.com
Fri Dec 4 14:46:56 PST 2009
Author: rjmccall
Date: Fri Dec 4 16:46:56 2009
New Revision: 90614
URL: http://llvm.org/viewvc/llvm-project?rev=90614&view=rev
Log:
Fix "using typename" and the instantiation of non-dependent using declarations.
Added:
cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/AST/TypeLoc.h
cfe/trunk/include/clang/AST/TypeLocBuilder.h
cfe/trunk/include/clang/AST/TypeNodes.def
cfe/trunk/include/clang/Frontend/PCHBitCodes.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/TypeLoc.cpp
cfe/trunk/lib/AST/TypePrinter.cpp
cfe/trunk/lib/CodeGen/Mangle.cpp
cfe/trunk/lib/Frontend/PCHReader.cpp
cfe/trunk/lib/Frontend/PCHWriter.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaCXX/using-decl-templates.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Dec 4 16:46:56 2009
@@ -57,6 +57,7 @@
class TypeDecl;
class TypedefDecl;
class UsingDecl;
+ class UsingShadowDecl;
namespace Builtin { class Context; }
@@ -183,8 +184,10 @@
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 @@
///
/// 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 @@
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);
-
- /// \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);
+ NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst);
+ /// \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);
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Dec 4 16:46:56 2009
@@ -76,6 +76,7 @@
class ObjCInterfaceDecl;
class ObjCProtocolDecl;
class ObjCMethodDecl;
+ class UnresolvedUsingTypenameDecl;
class Expr;
class Stmt;
class SourceLocation;
@@ -1863,6 +1864,38 @@
};
+/// \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:
Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Fri Dec 4 16:46:56 2009
@@ -340,16 +340,20 @@
}
};
+
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 @@
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 @@
}
};
-// 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> {
-};
-
-class FixedWidthIntTypeLoc : public TypeSpecTypeLoc<FixedWidthIntTypeLoc,
- FixedWidthIntType> {
-};
-
-class ComplexTypeLoc : public TypeSpecTypeLoc<ComplexTypeLoc,
- ComplexType> {
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ DependentSizedExtVectorTypeLoc,
+ DependentSizedExtVectorType> {
};
-class TypeOfExprTypeLoc : public TypeSpecTypeLoc<TypeOfExprTypeLoc,
- TypeOfExprType> {
+// FIXME: I'm not sure how you actually specify these; with attributes?
+class FixedWidthIntTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ FixedWidthIntTypeLoc,
+ FixedWidthIntType> {
};
-class TypeOfTypeLoc : public TypeSpecTypeLoc<TypeOfTypeLoc, TypeOfType> {
+// FIXME: location of the '_Complex' keyword.
+class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ ComplexTypeLoc,
+ ComplexType> {
};
-class DecltypeTypeLoc : public TypeSpecTypeLoc<DecltypeTypeLoc, DecltypeType> {
+// FIXME: location of the 'typeof' and parens (the expression is
+// carried by the type).
+class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TypeOfExprTypeLoc,
+ TypeOfExprType> {
};
-class TagTypeLoc : public TypeSpecTypeLoc<TagTypeLoc, TagType> {
+// 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 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> {
};
}
Modified: cfe/trunk/include/clang/AST/TypeLocBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLocBuilder.h?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLocBuilder.h (original)
+++ cfe/trunk/include/clang/AST/TypeLocBuilder.h Fri Dec 4 16:46:56 2009
@@ -59,9 +59,35 @@
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 @@
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 @@
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);
Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Fri Dec 4 16:46:56 2009
@@ -71,6 +71,7 @@
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)
Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Fri Dec 4 16:46:56 2009
@@ -404,7 +404,9 @@
/// \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
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Dec 4 16:46:56 2009
@@ -260,24 +260,40 @@
}
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 @@
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?");
Modified: cfe/trunk/lib/AST/TypeLoc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypeLoc.cpp (original)
+++ cfe/trunk/lib/AST/TypeLoc.cpp Fri Dec 4 16:46:56 2009
@@ -94,3 +94,32 @@
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);
+}
Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Fri Dec 4 16:46:56 2009
@@ -303,6 +303,15 @@
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;
Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Fri Dec 4 16:46:56 2009
@@ -843,6 +843,12 @@
// <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));
}
Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Dec 4 16:46:56 2009
@@ -1880,6 +1880,10 @@
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::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++]));
}
Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Fri Dec 4 16:46:56 2009
@@ -166,6 +166,14 @@
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::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);
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Dec 4 16:46:56 2009
@@ -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,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Dec 4 16:46:56 2009
@@ -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,
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Dec 4 16:46:56 2009
@@ -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)
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Dec 4 16:46:56 2009
@@ -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 =
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Dec 4 16:46:56 2009
@@ -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();
}
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Dec 4 16:46:56 2009
@@ -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>());
}
Added: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp?rev=90614&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp Fri Dec 4 16:46:56 2009
@@ -0,0 +1,183 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// C++03 [namespace.udecl]p4:
+// A using-declaration used as a member-declaration shall refer to a
+// member of a base class of the class being defined, shall refer to
+// a member of an 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.
+
+// There is no directly analogous paragraph in C++0x, and the feature
+// works sufficiently differently there that it needs a separate test.
+
+namespace test0 {
+ namespace NonClass {
+ typedef int type;
+ struct hiding {};
+ int hiding;
+ static union { double union_member; };
+ enum tagname { enumerator };
+ }
+
+ class Test0 {
+ using NonClass::type; // expected-error {{not a base class}}
+ using NonClass::hiding; // expected-error {{not a base class}}
+ using NonClass::union_member; // expected-error {{not a base class}}
+ using NonClass::enumerator; // expected-error {{not a base class}}
+ };
+}
+
+struct Opaque0 {};
+
+namespace test1 {
+ struct A {
+ typedef int type;
+ struct hiding {}; // expected-note {{previous use is here}}
+ Opaque0 hiding;
+ union { double union_member; };
+ enum tagname { enumerator };
+ };
+
+ struct B : A {
+ using A::type;
+ using A::hiding;
+ using A::union_member;
+ using A::enumerator;
+ using A::tagname;
+
+ void test0() {
+ type t = 0;
+ }
+
+ void test1() {
+ typedef struct A::hiding local;
+ struct hiding _ = local();
+ }
+
+ void test2() {
+ union hiding _; // expected-error {{tag type that does not match previous}}
+ }
+
+ void test3() {
+ char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+ }
+
+ void test4() {
+ enum tagname _ = enumerator;
+ }
+
+ void test5() {
+ Opaque0 _ = hiding;
+ }
+ };
+}
+
+namespace test2 {
+ struct A {
+ typedef int type;
+ struct hiding {}; // expected-note {{previous use is here}}
+ int hiding;
+ union { double union_member; };
+ enum tagname { enumerator };
+ };
+
+ template <class T> struct B : A {
+ using A::type;
+ using A::hiding;
+ using A::union_member;
+ using A::enumerator;
+ using A::tagname;
+
+ void test0() {
+ type t = 0;
+ }
+
+ void test1() {
+ typedef struct A::hiding local;
+ struct hiding _ = local();
+ }
+
+ void test2() {
+ union hiding _; // expected-error {{tag type that does not match previous}}
+ }
+
+ void test3() {
+ char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+ }
+
+ void test4() {
+ enum tagname _ = enumerator;
+ }
+
+ void test5() {
+ Opaque0 _ = hiding;
+ }
+ };
+}
+
+namespace test3 {
+ struct hiding {};
+
+ template <class T> struct A {
+ typedef int type; // expected-note {{target of using declaration}}
+ struct hiding {};
+ Opaque0 hiding; // expected-note {{target of using declaration}}
+ union { double union_member; }; // expected-note {{target of using declaration}}
+ enum tagname { enumerator }; // expected-note 2 {{target of using declaration}}
+ };
+
+ template <class T> struct B : A<T> {
+ using A<T>::type; // expected-error {{dependent using declaration resolved to type without 'typename'}}
+ using A<T>::hiding;
+ using A<T>::union_member;
+ using A<T>::enumerator;
+ using A<T>::tagname; // expected-error {{dependent using declaration resolved to type without 'typename'}}
+
+ // FIXME: re-enable these when the various bugs involving tags are fixed
+#if 0
+ void test1() {
+ typedef struct A<T>::hiding local;
+ struct hiding _ = local();
+ }
+
+ void test2() {
+ typedef struct A<T>::hiding local;
+ union hiding _ = local();
+ }
+#endif
+
+ void test3() {
+ char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+ }
+
+#if 0
+ void test4() {
+ enum tagname _ = enumerator;
+ }
+#endif
+
+ void test5() {
+ Opaque0 _ = hiding;
+ }
+ };
+
+ template struct B<int>; // expected-note {{in instantiation}}
+
+ template <class T> struct C : A<T> {
+ using typename A<T>::type;
+ using typename A<T>::hiding; // expected-error {{'typename' keyword used on a non-type}}
+ using typename A<T>::union_member; // expected-error {{'typename' keyword used on a non-type}}
+ using typename A<T>::enumerator; // expected-error {{'typename' keyword used on a non-type}}
+
+ void test6() {
+ type t = 0;
+ }
+
+ void test7() {
+ Opaque0 _ = hiding; // expected-error {{expected '(' for function-style cast or type construction}}
+ }
+ };
+
+ template struct C<int>; // expected-note {{in instantiation}}
+}
Modified: cfe/trunk/test/SemaCXX/using-decl-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/using-decl-templates.cpp?rev=90614&r1=90613&r2=90614&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/using-decl-templates.cpp (original)
+++ cfe/trunk/test/SemaCXX/using-decl-templates.cpp Fri Dec 4 16:46:56 2009
@@ -34,3 +34,14 @@
void g() { f(); }
};
+
+namespace test0 {
+ struct Base {
+ int foo;
+ };
+ template<typename T> struct E : Base {
+ using Base::foo;
+ };
+
+ template struct E<int>;
+}
More information about the cfe-commits
mailing list