[cfe-commits] r65649 - in /cfe/trunk: lib/Sema/CMakeLists.txt lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiation-default-1.cpp

Douglas Gregor dgregor at apple.com
Fri Feb 27 11:31:53 PST 2009


Author: dgregor
Date: Fri Feb 27 13:31:52 2009
New Revision: 65649

URL: http://llvm.org/viewvc/llvm-project?rev=65649&view=rev
Log:
Implement the basic approach for instantiating types, with a lot of FIXME'd
stubs for those types we don't yet know how to instantiate (everything
that isn't a template parameter!).

We now instantiate default arguments for template type parameters when
needed. This will be our testbed while I fill out the remaining
type-instantiation logic.


Added:
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
Modified:
    cfe/trunk/lib/Sema/CMakeLists.txt
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=65649&r1=65648&r2=65649&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Fri Feb 27 13:31:52 2009
@@ -21,5 +21,6 @@
   SemaOverload.cpp
   SemaStmt.cpp
   SemaTemplate.cpp
+  SemaTemplateInstantiate.cpp
   SemaType.cpp
   )

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=65649&r1=65648&r2=65649&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Feb 27 13:31:52 2009
@@ -1579,6 +1579,13 @@
   bool CheckTemplateDeclScope(Scope *S, 
                               MultiTemplateParamsArg &TemplateParameterLists);
 
+  //===--------------------------------------------------------------------===//
+  // C++ Template Instantiation
+  //
+  QualType InstantiateType(QualType T, const TemplateArgument *TemplateArgs,
+                           unsigned NumTemplateArgs,
+                           SourceLocation Loc, DeclarationName Entity);
+
   // Objective-C declarations.
   virtual DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
                                            IdentifierInfo *ClassName,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=65649&r1=65648&r2=65649&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Feb 27 13:31:52 2009
@@ -5,11 +5,11 @@
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
-//+//===----------------------------------------------------------------------===/
+//===----------------------------------------------------------------------===/
 
 //
 //  This file implements semantic analysis for C++ templates.
-//+//===----------------------------------------------------------------------===/
+//===----------------------------------------------------------------------===/
 
 #include "Sema.h"
 #include "clang/AST/ASTContext.h"
@@ -757,6 +757,17 @@
           break;
 
         ArgType = TTP->getDefaultArgument();
+
+        // If the argument type is dependent, instantiate it now based
+        // on the previously-computed template arguments.
+        if (ArgType->isDependentType())
+          ArgType = InstantiateType(ArgType, &Converted[0], Converted.size(),
+                                    TTP->getDefaultArgumentLoc(),
+                                    TTP->getDeclName());
+
+        if (ArgType.isNull())
+          break;
+
         ArgLoc = TTP->getDefaultArgumentLoc();
       } else if (NonTypeTemplateParmDecl *NTTP 
                    = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {

Added: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=65649&view=auto

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (added)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Feb 27 13:31:52 2009
@@ -0,0 +1,438 @@
+//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements C++ template instantiation.
+//
+//===----------------------------------------------------------------------===/
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Basic/LangOptions.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===/
+// Template Instantiation for Types
+//===----------------------------------------------------------------------===/
+
+static QualType PerformTypeInstantiation(Sema &SemaRef, 
+                                         const ExtQualType *T, 
+                                         unsigned CVR,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceLocation Loc,
+                                         DeclarationName Entity) {
+  // 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) {
+  assert(false && "BuiltinType is never dependent and cannot be instantiated");
+  return QualType(T, CVR);
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef, 
+                                         const FixedWidthIntType *T, 
+                                         unsigned CVR,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceLocation Loc,
+                                         DeclarationName Entity) {
+  // 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) {
+  // 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();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef, 
+                                         const BlockPointerType *T,
+                                         unsigned CVR,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceLocation Loc,
+                                         DeclarationName Entity) {
+  // 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();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef, 
+                                         const MemberPointerType *T, 
+                                         unsigned CVR,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceLocation Loc,
+                                         DeclarationName Entity) {
+  // 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();
+}
+
+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();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef, 
+                                         const VariableArrayType *T, 
+                                         unsigned CVR,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceLocation Loc,
+                                         DeclarationName Entity) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  // 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) {
+  if (T->getDepth() == 0) {
+    // Replace the template type parameter with its corresponding
+    // template argument.
+    assert(T->getIndex() < NumTemplateArgs && "Wrong # of template args");
+    assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
+           "Template argument kind mismatch");
+    QualType Result = TemplateArgs[T->getIndex()].getAsType();
+    if (Result.isNull() || !CVR) 
+      return Result;
+
+    // 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.
+    if (CVR && Result->isReferenceType())
+      CVR = 0;
+
+    return QualType(Result.getTypePtr(), CVR | Result.getCVRQualifiers());
+  } 
+
+  // The template type parameter comes from an inner template (e.g.,
+  // the template parameter list of a member template inside the
+  // template we are instantiating). Create a new template type
+  // parameter with the template "level" reduced by one.
+  return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
+                                                 T->getIndex(),
+                                                 T->getName());
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef, 
+                                     const ClassTemplateSpecializationType *T, 
+                                         unsigned CVR,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceLocation Loc,
+                                         DeclarationName Entity) {
+  // 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");
+  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");
+  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");
+  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");
+  return QualType();
+}
+
+
+/// \brief Instantiate the type T with a given set of template arguments.
+///
+/// This routine substitutes the given template arguments into the
+/// type T and produces the instantiated type.
+///
+/// \param T the type into which the template arguments will be
+/// substituted. If this type is not dependent, it will be returned
+/// immediately.
+///
+/// \param TemplateArgs the template arguments that will be
+/// substituted for the top-level template parameters within T.
+///
+/// \param NumTemplateArgs the number of template arguments provided
+/// by TemplateArgs.
+///
+/// \param Loc the location in the source code where this substitution
+/// is being performed. It will typically be the location of the
+/// declarator (if we're instantiating the type of some declaration)
+/// or the location of the type in the source code (if, e.g., we're
+/// instantiating the type of a cast expression).
+///
+/// \param Entity the name of the entity associated with a declaration
+/// being instantiated (if any). May be empty to indicate that there
+/// is no such entity (if, e.g., this is a type that occurs as part of
+/// a cast expression) or that the entity has no name (e.g., an
+/// unnamed function parameter).
+///
+/// \returns If the instantiation succeeds, the instantiated
+/// type. Otherwise, produces diagnostics and returns a NULL type.
+QualType Sema::InstantiateType(QualType T, 
+                               const TemplateArgument *TemplateArgs,
+                               unsigned NumTemplateArgs,
+                               SourceLocation Loc, DeclarationName Entity) {
+  // 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 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 hav been decided for template instantiation");
+  return QualType();
+}

Added: cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp?rev=65649&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp Fri Feb 27 13:31:52 2009
@@ -0,0 +1,19 @@
+// RUN: clang -fsyntax-only -verify %s
+
+template<typename T, typename U = const T> struct Def1;
+
+template<> struct Def1<int> { 
+  void foo();
+};
+
+template<> struct Def1<const int> { // expected-note{{previous definition is here}}
+  void bar();
+};
+
+void test_Def1(Def1<int, const int> *d1, Def1<const int, const int> *d2) {
+  d1->foo();
+  d2->bar();
+}
+
+template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1'}}
+





More information about the cfe-commits mailing list