]> granicus.if.org Git - clang/commitdiff
Implement template instantiation for pointer, reference, and (some)
authorDouglas Gregor <dgregor@apple.com>
Sat, 28 Feb 2009 00:25:32 +0000 (00:25 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 28 Feb 2009 00:25:32 +0000 (00:25 +0000)
array types. Semantic checking for the construction of these types has
been factored out of GetTypeForDeclarator and into separate
subroutines (BuildPointerType, BuildReferenceType,
BuildArrayType). We'll be doing the same thing for all other types
(and declarations and expressions).

As part of this, moved the type-instantiation functions into a class
in an anonymous namespace.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65663 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaType.cpp
test/SemaTemplate/instantiation-default-1.cpp

index 7875a8183b8eab8396000bbb82120c49ba419cd1..7a5a10287f275fd28b77f306e4c5adcadd5d8c96 100644 (file)
@@ -232,6 +232,13 @@ public:
   //
   QualType ConvertDeclSpecToType(const DeclSpec &DS);
   void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
+  QualType BuildPointerType(QualType T, unsigned Quals, 
+                            SourceLocation Loc, DeclarationName Entity);
+  QualType BuildReferenceType(QualType T, unsigned Quals, 
+                              SourceLocation Loc, DeclarationName Entity);
+  QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
+                          Expr *ArraySize, unsigned Quals,
+                          SourceLocation Loc, DeclarationName Entity);
   QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0);
   DeclarationName GetNameForDeclarator(Declarator &D);
 
index aabbffa4c3d8a3014605680f780fa4633828c06d..54f1d87cc8dff04cc766820d5291698d2aa3099f 100644 (file)
@@ -766,7 +766,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
                                     TTP->getDeclName());
 
         if (ArgType.isNull())
-          break;
+          return true;
 
         ArgLoc = TTP->getDefaultArgumentLoc();
       } else if (NonTypeTemplateParmDecl *NTTP 
index 1e7569a9b250ffea2faf5353960ccc362aca225f..f864a50c5ec9543ad5b5b3939a6d7d03a99af653 100644 (file)
 #include "clang/AST/DeclTemplate.h"
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Basic/LangOptions.h"
+#include "llvm/Support/Compiler.h"
 
 using namespace clang;
 
 //===----------------------------------------------------------------------===/
 // Template Instantiation for Types
 //===----------------------------------------------------------------------===/
+namespace {
+  class VISIBILITY_HIDDEN TemplateTypeInstantiator {
+    Sema &SemaRef;
+    const TemplateArgument *TemplateArgs;
+    unsigned NumTemplateArgs;
+    SourceLocation Loc;
+    DeclarationName Entity;
+
+  public:
+    TemplateTypeInstantiator(Sema &SemaRef, 
+                             const TemplateArgument *TemplateArgs,
+                             unsigned NumTemplateArgs,
+                             SourceLocation Loc,
+                             DeclarationName Entity) 
+      : SemaRef(SemaRef), TemplateArgs(TemplateArgs), 
+        NumTemplateArgs(NumTemplateArgs), Loc(Loc), Entity(Entity) { }
+
+    QualType operator()(QualType T) const { return Instantiate(T); }
+    
+    QualType Instantiate(QualType T) const;
+
+    // Declare instantiate functions for each type.
+#define TYPE(Class, Base)                                       \
+    QualType Instantiate##Class##Type(const Class##Type *T,     \
+                                      unsigned Quals) const;
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+  };
+}
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ExtQualType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T,
+                                                 unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate ExtQualType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const BuiltinType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T,
+                                                 unsigned Quals) const {
   assert(false && "BuiltinType is never dependent and cannot be instantiated");
-  return QualType(T, CVR);
+  return QualType(T, Quals);
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const FixedWidthIntType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::
+InstantiateFixedWidthIntType(const FixedWidthIntType *T, unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate FixedWidthIntType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ComplexType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T,
+                                                 unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate ComplexType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const PointerType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate PointerType yet");
-  return QualType();
+QualType 
+TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T,
+                                                 unsigned Quals) const {
+  QualType PointeeType = Instantiate(T->getPointeeType());
+  if (PointeeType.isNull())
+    return QualType();
+
+  return SemaRef.BuildPointerType(PointeeType, Quals, Loc, Entity);
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const BlockPointerType *T,
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T,
+                                                      unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate BlockPointerType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ReferenceType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ReferenceType yet");
-  return QualType();
+QualType 
+TemplateTypeInstantiator::InstantiateReferenceType(const ReferenceType *T, 
+                                                   unsigned Quals) const {
+  QualType ReferentType = Instantiate(T->getPointeeType());
+  if (ReferentType.isNull())
+    return QualType();
+
+  return SemaRef.BuildReferenceType(ReferentType, Quals, Loc, Entity);
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const MemberPointerType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::
+InstantiateMemberPointerType(const MemberPointerType *T,
+                             unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate MemberPointerType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ConstantArrayType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ConstantArrayType yet");
-  return QualType();
+QualType 
+TemplateTypeInstantiator::
+InstantiateConstantArrayType(const ConstantArrayType *T, 
+                             unsigned Quals) const {
+  QualType ElementType = Instantiate(T->getElementType());
+  if (ElementType.isNull())
+    return ElementType;
+  
+  // Build a temporary integer literal to specify the size for
+  // BuildArrayType. Since we have already checked the size as part of
+  // creating the dependent array type in the first place, we know
+  // there aren't any errors.
+  IntegerLiteral ArraySize(T->getSize(), SemaRef.Context.IntTy, Loc);
+  return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), 
+                                &ArraySize, T->getIndexTypeQualifier(), 
+                                Loc, Entity);
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const IncompleteArrayType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate IncompleteArrayType yet");
-  return QualType();
+QualType 
+TemplateTypeInstantiator::
+InstantiateIncompleteArrayType(const IncompleteArrayType *T,
+                               unsigned Quals) const {
+  QualType ElementType = Instantiate(T->getElementType());
+  if (ElementType.isNull())
+    return ElementType;
+  
+  return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), 
+                                0, T->getIndexTypeQualifier(), 
+                                Loc, Entity);
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const VariableArrayType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType
+TemplateTypeInstantiator::
+InstantiateVariableArrayType(const VariableArrayType *T,
+                             unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate VariableArrayType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const DependentSizedArrayType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::
+InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
+                                   unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate DependentSizedArrayType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const VectorType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T,
+                                             unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate VectorType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ExtVectorType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateExtVectorType(const ExtVectorType *T,
+                                                   unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate ExtVectorType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const FunctionProtoType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::
+InstantiateFunctionProtoType(const FunctionProtoType *T,
+                             unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate FunctionProtoType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const FunctionNoProtoType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::
+InstantiateFunctionNoProtoType(const FunctionNoProtoType *T,
+                               unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate FunctionNoProtoType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const TypedefType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
+                                                 unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate TypedefType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const TypeOfExprType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T,
+                                                    unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate TypeOfExprType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const TypeOfType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T,
+                                                unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate TypeOfType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const RecordType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
+                                                unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate RecordType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const CXXRecordType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateCXXRecordType(const CXXRecordType *T,
+                                                   unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate CXXRecordType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const EnumType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
+                                              unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate EnumType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const TemplateTypeParmType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::
+InstantiateTemplateTypeParmType(const TemplateTypeParmType *T,
+                                unsigned Quals) const {
   if (T->getDepth() == 0) {
     // Replace the template type parameter with its corresponding
     // template argument.
@@ -301,7 +264,7 @@ static QualType PerformTypeInstantiation(Sema &SemaRef,
     assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
            "Template argument kind mismatch");
     QualType Result = TemplateArgs[T->getIndex()].getAsType();
-    if (Result.isNull() || !CVR
+    if (Result.isNull() || !Quals
       return Result;
 
     // C++ [dcl.ref]p1:
@@ -309,10 +272,10 @@ static QualType PerformTypeInstantiation(Sema &SemaRef,
     //   the cv-qualifiers are introduced through the use of a
     //   typedef (7.1.3) or of a template type argument (14.3), in
     //   which case the cv-qualifiers are ignored.
-    if (CVR && Result->isReferenceType())
-      CVR = 0;
+    if (Quals && Result->isReferenceType())
+      Quals = 0;
 
-    return QualType(Result.getTypePtr(), CVR | Result.getCVRQualifiers());
+    return QualType(Result.getTypePtr(), Quals | Result.getCVRQualifiers());
   } 
 
   // The template type parameter comes from an inner template (e.g.,
@@ -321,69 +284,70 @@ static QualType PerformTypeInstantiation(Sema &SemaRef,
   // parameter with the template "level" reduced by one.
   return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
                                                  T->getIndex(),
-                                                 T->getName());
+                                                 T->getName())
+    .getQualifiedType(Quals);
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                     const ClassTemplateSpecializationType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
+QualType 
+TemplateTypeInstantiator::
+InstantiateClassTemplateSpecializationType(
+                                  const ClassTemplateSpecializationType *T,
+                                  unsigned Quals) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate ClassTemplateSpecializationType yet");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ObjCInterfaceType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ObjCInterfaceType yet");
+QualType 
+TemplateTypeInstantiator::
+InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
+                             unsigned Quals) const {
+  assert(false && "Objective-C types cannot be dependent");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ObjCQualifiedInterfaceType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ObjCQualifiedInterfaceType yet");
+QualType 
+TemplateTypeInstantiator::
+InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
+                                      unsigned Quals) const {
+  assert(false && "Objective-C types cannot be dependent");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ObjCQualifiedIdType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ObjCQualifiedIdType yet");
+QualType 
+TemplateTypeInstantiator::
+InstantiateObjCQualifiedIdType(const ObjCQualifiedIdType *T,
+                               unsigned Quals) const {
+  assert(false && "Objective-C types cannot be dependent");
   return QualType();
 }
 
-static QualType PerformTypeInstantiation(Sema &SemaRef, 
-                                         const ObjCQualifiedClassType *T, 
-                                         unsigned CVR,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs,
-                                         SourceLocation Loc,
-                                         DeclarationName Entity) {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ObjCQualifiedClassType yet");
+QualType 
+TemplateTypeInstantiator::
+InstantiateObjCQualifiedClassType(const ObjCQualifiedClassType *T,
+                                  unsigned Quals) const {
+  assert(false && "Objective-C types cannot be dependent");
   return QualType();
 }
 
+/// \brief The actual implementation of Sema::InstantiateType().
+QualType TemplateTypeInstantiator::Instantiate(QualType T) const {
+  // If T is not a dependent type, there is nothing to do.
+  if (!T->isDependentType())
+    return T;
+
+  switch (T->getTypeClass()) {
+#define TYPE(Class, Base)                                               \
+  case Type::Class:                                                     \
+    return Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr()),  \
+                                    T.getCVRQualifiers());
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+  }
+  
+  assert(false && "Not all types have been decoded for instantiation");
+  return QualType();
+}
 
 /// \brief Instantiate the type T with a given set of template arguments.
 ///
@@ -422,17 +386,7 @@ QualType Sema::InstantiateType(QualType T,
   if (!T->isDependentType())
     return T;
 
-  switch (T->getTypeClass()) {
-#define TYPE(Class, Base)                                               \
-  case Type::Class:                                                     \
-    return PerformTypeInstantiation(*this,                              \
-                                    cast<Class##Type>(T.getTypePtr()),  \
-                                    T.getCVRQualifiers(), TemplateArgs, \
-                                    NumTemplateArgs, Loc, Entity);
-#define ABSTRACT_TYPE(Class, Base)
-#include "clang/AST/TypeNodes.def"
-  }
-  
-  assert(false && "Not all types have been decoded for instantiation");
-  return QualType();
+  TemplateTypeInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs,
+                                        Loc, Entity);
+  return Instantiator(T);
 }
index a1c5dbc4d10c8867a7b97e86f02dda8fd624d649..bc2bce3883aee17a0ae7be328185bbd97e32c085 100644 (file)
@@ -260,6 +260,215 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
   return Result;
 }
 
+static std::string getPrintableNameForEntity(DeclarationName Entity) {
+  if (Entity)
+    return Entity.getAsString();
+  
+  return "type name";
+}
+
+/// \brief Build a pointer type.
+///
+/// \param T The type to which we'll be building a pointer.
+///
+/// \param Quals The cvr-qualifiers to be applied to the pointer type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// pointer type or, if there is no such entity, the location of the
+/// type that will have pointer type.
+///
+/// \param Entity The name of the entity that involves the pointer
+/// type, if known.
+///
+/// \returns A suitable pointer type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildPointerType(QualType T, unsigned Quals, 
+                                SourceLocation Loc, DeclarationName Entity) {
+  if (T->isReferenceType()) {
+    // C++ 8.3.2p4: There shall be no ... pointers to references ...
+    Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
+      << getPrintableNameForEntity(Entity);
+    return QualType();
+  }
+
+  // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+  // object or incomplete types shall not be restrict-qualified."
+  if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+    Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
+      << T;
+    Quals &= ~QualType::Restrict;
+  }
+
+  // Build the pointer type.
+  return Context.getPointerType(T).getQualifiedType(Quals);
+}
+
+/// \brief Build a reference type.
+///
+/// \param T The type to which we'll be building a reference.
+///
+/// \param Quals The cvr-qualifiers to be applied to the reference type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// reference type or, if there is no such entity, the location of the
+/// type that will have reference type.
+///
+/// \param Entity The name of the entity that involves the reference
+/// type, if known.
+///
+/// \returns A suitable reference type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildReferenceType(QualType T, unsigned Quals, 
+                                  SourceLocation Loc, DeclarationName Entity) {
+  if (T->isReferenceType()) {
+    // C++ [dcl.ref]p4: There shall be no references to references.
+    // 
+    // According to C++ DR 106, references to references are only
+    // diagnosed when they are written directly (e.g., "int & &"),
+    // but not when they happen via a typedef:
+    //
+    //   typedef int& intref;
+    //   typedef intref& intref2;
+    //
+    // Parser::ParserDeclaratorInternal diagnoses the case where
+    // references are written directly; here, we handle the
+    // collapsing of references-to-references as described in C++
+    // DR 106 and amended by C++ DR 540.
+    return T;
+  }
+
+  // C++ [dcl.ref]p1:
+  //   A declarator that specifies the type “reference to cv void”
+  //   is ill-formed.
+  if (T->isVoidType()) {
+    Diag(Loc, diag::err_reference_to_void);
+    return QualType();
+  }
+
+  // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+  // object or incomplete types shall not be restrict-qualified."
+  if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+    Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
+      << T;
+    Quals &= ~QualType::Restrict;
+  }
+
+  // C++ [dcl.ref]p1:
+  //   [...] Cv-qualified references are ill-formed except when the
+  //   cv-qualifiers are introduced through the use of a typedef
+  //   (7.1.3) or of a template type argument (14.3), in which case
+  //   the cv-qualifiers are ignored.
+  //
+  // We diagnose extraneous cv-qualifiers for the non-typedef,
+  // non-template type argument case within the parser. Here, we just
+  // ignore any extraneous cv-qualifiers.
+  Quals &= ~QualType::Const;
+  Quals &= ~QualType::Volatile;
+
+  // Handle restrict on references.
+  return Context.getReferenceType(T).getQualifiedType(Quals);
+}
+
+/// \brief Build an array type.
+///
+/// \param T The type of each element in the array.
+///
+/// \param ASM C99 array size modifier (e.g., '*', 'static').
+///  
+/// \param ArraySize Expression describing the size of the array. 
+///
+/// \param Quals The cvr-qualifiers to be applied to the array's
+/// element type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// array type or, if there is no such entity, the location of the
+/// type that will have array type.
+///
+/// \param Entity The name of the entity that involves the array
+/// type, if known.
+///
+/// \returns A suitable array type, if there are no errors. Otherwise,
+/// returns a NULL type.
+QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
+                              Expr *ArraySize, unsigned Quals,
+                              SourceLocation Loc, DeclarationName Entity) {
+  // C99 6.7.5.2p1: If the element type is an incomplete or function type, 
+  // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
+  if (DiagnoseIncompleteType(Loc, T, 
+                             diag::err_illegal_decl_array_incomplete_type))
+    return QualType();
+
+  if (T->isFunctionType()) {
+    Diag(Loc, diag::err_illegal_decl_array_of_functions)
+      << getPrintableNameForEntity(Entity);
+    return QualType();
+  }
+    
+  // C++ 8.3.2p4: There shall be no ... arrays of references ...
+  if (T->isReferenceType()) {
+    Diag(Loc, diag::err_illegal_decl_array_of_references)
+      << getPrintableNameForEntity(Entity);
+    return QualType();
+  } 
+
+  if (const RecordType *EltTy = T->getAsRecordType()) {
+    // If the element type is a struct or union that contains a variadic
+    // array, accept it as a GNU extension: C99 6.7.2.1p2.
+    if (EltTy->getDecl()->hasFlexibleArrayMember())
+      Diag(Loc, diag::ext_flexible_array_in_array) << T;
+  } else if (T->isObjCInterfaceType()) {
+    Diag(Loc, diag::warn_objc_array_of_interfaces) << T;
+  }
+      
+  // C99 6.7.5.2p1: The size expression shall have integer type.
+  if (ArraySize && !ArraySize->isTypeDependent() &&
+      !ArraySize->getType()->isIntegerType()) {
+    Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
+      << ArraySize->getType() << ArraySize->getSourceRange();
+    ArraySize->Destroy(Context);
+    return QualType();
+  }
+  llvm::APSInt ConstVal(32);
+  if (!ArraySize) {
+    T = Context.getIncompleteArrayType(T, ASM, Quals);
+  } else if (ArraySize->isValueDependent()) {
+    T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals);
+  } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
+             (!T->isDependentType() && !T->isConstantSizeType())) {
+    // Per C99, a variable array is an array with either a non-constant
+    // size or an element type that has a non-constant-size
+    T = Context.getVariableArrayType(T, ArraySize, ASM, Quals);
+  } else {
+    // C99 6.7.5.2p1: If the expression is a constant expression, it shall
+    // have a value greater than zero.
+    if (ConstVal.isSigned()) {
+      if (ConstVal.isNegative()) {
+        Diag(ArraySize->getLocStart(),
+             diag::err_typecheck_negative_array_size)
+          << ArraySize->getSourceRange();
+        return QualType();
+      } else if (ConstVal == 0) {
+        // GCC accepts zero sized static arrays.
+        Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
+          << ArraySize->getSourceRange();
+      }
+    } 
+    T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
+  }
+  // If this is not C99, extwarn about VLA's and C99 array size modifiers.
+  if (!getLangOptions().C99) {
+    if (ArraySize && !ArraySize->isTypeDependent() && 
+        !ArraySize->isValueDependent() && 
+        !ArraySize->isIntegerConstantExpr(Context))
+      Diag(Loc, diag::ext_vla);
+    else if (ASM != ArrayType::Normal || Quals != 0)
+      Diag(Loc, diag::ext_c99_array_usage);
+  }
+
+  return T;
+}
+                              
+
 /// GetTypeForDeclarator - Convert the type for the specified
 /// declarator to Type instances. Skip the outermost Skip type
 /// objects.
@@ -309,6 +518,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
     break;
   }
 
+  // The name we're declaring, if any.
+  DeclarationName Name;
+  if (D.getIdentifier())
+    Name = D.getIdentifier();
+
   // Walk the DeclTypeInfo, building the recursive type as we go.
   // DeclTypeInfos are ordered from the identifier out, which is
   // opposite of what we want :).
@@ -325,72 +539,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
         T = Context.getBlockPointerType(T);
       break;
     case DeclaratorChunk::Pointer:
-      if (T->isReferenceType()) {
-        // C++ 8.3.2p4: There shall be no ... pointers to references ...
-        Diag(DeclType.Loc, diag::err_illegal_decl_pointer_to_reference)
-         << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
-        D.setInvalidType(true);
-        T = Context.IntTy;
-      }
-
-      // Enforce C99 6.7.3p2: "Types other than pointer types derived from
-      // object or incomplete types shall not be restrict-qualified."
-      if ((DeclType.Ptr.TypeQuals & QualType::Restrict) &&
-          !T->isIncompleteOrObjectType()) {
-        Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
-          << T;
-        DeclType.Ptr.TypeQuals &= ~QualType::Restrict;
-      }
-
-      // Apply the pointer typequals to the pointer object.
-      T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals);
+      T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
       break;
-    case DeclaratorChunk::Reference: {
-      // Whether we should suppress the creation of the reference.
-      bool SuppressReference = false;
-      if (T->isReferenceType()) {
-        // C++ [dcl.ref]p4: There shall be no references to references.
-        // 
-        // According to C++ DR 106, references to references are only
-        // diagnosed when they are written directly (e.g., "int & &"),
-        // but not when they happen via a typedef:
-        //
-        //   typedef int& intref;
-        //   typedef intref& intref2;
-        //
-        // Parser::ParserDeclaratorInternal diagnoses the case where
-        // references are written directly; here, we handle the
-        // collapsing of references-to-references as described in C++
-        // DR 106 and amended by C++ DR 540.
-        SuppressReference = true;
-      }
-
-      // C++ [dcl.ref]p1:
-      //   A declarator that specifies the type “reference to cv void”
-      //   is ill-formed.
-      if (T->isVoidType()) {
-        Diag(DeclType.Loc, diag::err_reference_to_void);
-        D.setInvalidType(true);
-        T = Context.IntTy;
-      }
-
-      // Enforce C99 6.7.3p2: "Types other than pointer types derived from
-      // object or incomplete types shall not be restrict-qualified."
-      if (DeclType.Ref.HasRestrict &&
-          !T->isIncompleteOrObjectType()) {
-        Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
-          << T;
-        DeclType.Ref.HasRestrict = false;
-      }        
-
-      if (!SuppressReference)
-        T = Context.getReferenceType(T);
-
-      // Handle restrict on references.
-      if (DeclType.Ref.HasRestrict)
-        T.addRestrict();
+    case DeclaratorChunk::Reference:
+      T = BuildReferenceType(T, 
+                             DeclType.Ref.HasRestrict? QualType::Restrict : 0,
+                             DeclType.Loc, Name);
       break;
-    }
     case DeclaratorChunk::Array: {
       DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
       Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
@@ -401,76 +556,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
         ASM = ArrayType::Static;
       else
         ASM = ArrayType::Normal;
-
-      // C99 6.7.5.2p1: If the element type is an incomplete or function type, 
-      // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
-      if (DiagnoseIncompleteType(D.getIdentifierLoc(), T, 
-                                 diag::err_illegal_decl_array_incomplete_type)) {
-        T = Context.IntTy;
-        D.setInvalidType(true);
-      } else if (T->isFunctionType()) {
-        Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions)
-          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
-        T = Context.getPointerType(T);
-        D.setInvalidType(true);
-      } else if (const ReferenceType *RT = T->getAsReferenceType()) {
-        // C++ 8.3.2p4: There shall be no ... arrays of references ...
-        Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_references)
-          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
-        T = RT->getPointeeType();
-        D.setInvalidType(true);
-      } else if (const RecordType *EltTy = T->getAsRecordType()) {
-        // If the element type is a struct or union that contains a variadic
-        // array, accept it as a GNU extension: C99 6.7.2.1p2.
-        if (EltTy->getDecl()->hasFlexibleArrayMember())
-          Diag(DeclType.Loc, diag::ext_flexible_array_in_array) << T;
-      } else if (T->isObjCInterfaceType()) {
-        Diag(DeclType.Loc, diag::warn_objc_array_of_interfaces) << T;
-      }
-      
-      // C99 6.7.5.2p1: The size expression shall have integer type.
-      if (ArraySize && !ArraySize->getType()->isIntegerType()) {
-        Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
-          << ArraySize->getType() << ArraySize->getSourceRange();
-        D.setInvalidType(true);
-        ArraySize->Destroy(Context);
-        ATI.NumElts = ArraySize = 0;
-      }
-      llvm::APSInt ConstVal(32);
-      if (!ArraySize) {
-        T = Context.getIncompleteArrayType(T, ASM, ATI.TypeQuals);
-      } else if (ArraySize->isValueDependent()) {
-        T = Context.getDependentSizedArrayType(T, ArraySize, ASM, ATI.TypeQuals);
-      } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
-                 !T->isConstantSizeType()) {
-        // Per C99, a variable array is an array with either a non-constant
-        // size or an element type that has a non-constant-size
-        T = Context.getVariableArrayType(T, ArraySize, ASM, ATI.TypeQuals);
-      } else {
-        // C99 6.7.5.2p1: If the expression is a constant expression, it shall
-        // have a value greater than zero.
-        if (ConstVal.isSigned()) {
-          if (ConstVal.isNegative()) {
-            Diag(ArraySize->getLocStart(),
-                 diag::err_typecheck_negative_array_size)
-              << ArraySize->getSourceRange();
-            D.setInvalidType(true);
-          } else if (ConstVal == 0) {
-            // GCC accepts zero sized static arrays.
-            Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
-              << ArraySize->getSourceRange();
-          }
-        } 
-        T = Context.getConstantArrayType(T, ConstVal, ASM, ATI.TypeQuals);
-      }
-      // If this is not C99, extwarn about VLA's and C99 array size modifiers.
-      if (!getLangOptions().C99) {
-        if (ArraySize && !ArraySize->isValueDependent() && 
-            !ArraySize->isIntegerConstantExpr(Context))
-          Diag(D.getIdentifierLoc(), diag::ext_vla);
-        else if (ASM != ArrayType::Normal || ATI.TypeQuals != 0)
-          Diag(D.getIdentifierLoc(), diag::ext_c99_array_usage);
-      }
+      T = BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals, DeclType.Loc, Name);
       break;
     }
     case DeclaratorChunk::Function: {
@@ -632,6 +718,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
       break;
     }
 
+    if (T.isNull()) {
+      D.setInvalidType(true);
+      T = Context.IntTy;
+    }
+
     // See if there are any attributes on this declarator chunk.
     if (const AttributeList *AL = DeclType.getAttrs())
       ProcessTypeAttributeList(T, AL);
index cc616ac770fcbc204a627848fd58521b89b4fcb8..026e879bd3e6a45e1694c0da7cf220fc6c59c91c 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: clang -fsyntax-only -verify %s
-
 template<typename T, typename U = const T> struct Def1;
 
 template<> struct Def1<int> { 
@@ -10,10 +9,72 @@ template<> struct Def1<const int> { // expected-note{{previous definition is her
   void bar();
 };
 
-void test_Def1(Def1<int, const int> *d1, Def1<const int, const int> *d2) {
+template<> struct Def1<int&> {
+  void wibble();
+};
+
+void test_Def1(Def1<int, const int> *d1, Def1<const int, const int> *d2,
+               Def1<int&, int&> *d3) {
   d1->foo();
   d2->bar();
+  d3->wibble();
+}
+
+template<typename T,  // FIXME: bad error message below, needs better location info
+         typename T2 = const T*>  // expected-error{{'T2' declared as a pointer to a reference}}
+  struct Def2;
+
+template<> struct Def2<int> { 
+  void foo();
+};
+
+void test_Def2(Def2<int, int const*> *d2) {
+  d2->foo();
 }
 
+Def2<int&> *d2;
+
+
 template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1'}}
 
+template<typename T, typename T2 = T&> struct Def3;
+
+template<> struct Def3<int> { 
+  void foo();
+};
+
+template<> struct Def3<int&> { 
+  void bar();
+};
+
+void test_Def3(Def3<int, int&> *d3a, Def3<int&, int&> *d3b) {
+  d3a->foo();
+  d3b->bar();
+}
+
+
+template<typename T, typename T2 = T[]> struct Def4;
+
+template<> struct Def4<int> {
+  void foo();
+};
+
+void test_Def4(Def4<int, int[]> *d4a) {
+  d4a->foo();
+}
+
+template<typename T, typename T2 = T const[12]> struct Def5;
+
+template<> struct Def5<int> {
+  void foo();
+};
+
+template<> struct Def5<int, int const[13]> {
+  void bar();
+};
+
+void test_Def5(Def5<int, const int[12]> *d5a, Def5<int, const int[13]> *d5b) {
+  d5a->foo();
+  d5b->bar();
+}
+