]> granicus.if.org Git - clang/commitdiff
Eliminate TemplateArg so that we only have a single kind of
authorDouglas Gregor <dgregor@apple.com>
Mon, 9 Feb 2009 19:34:22 +0000 (19:34 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 9 Feb 2009 19:34:22 +0000 (19:34 +0000)
representation for template arguments. Also simplifies the interface
for ActOnClassTemplateSpecialization and eliminates some annoying
allocations of TemplateArgs.

My attempt at smart pointers for template arguments lists is
relatively lame. We can improve it once we're sure that we have the
right representation for template arguments.

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

include/clang/AST/DeclTemplate.h
include/clang/AST/Type.h
include/clang/Parse/Action.h
include/clang/Parse/Ownership.h
include/clang/Parse/Parser.h
lib/AST/DeclTemplate.cpp
lib/AST/Type.cpp
lib/Parse/ParseTemplate.cpp
lib/Sema/Sema.h
lib/Sema/SemaTemplate.cpp

index daf4210c443084adca15b666d786115bef62abeb..b466a118b17582d4d8b946abece7fbd8bb9ff2a1 100644 (file)
@@ -336,35 +336,6 @@ protected:
   friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
 };
 
-class TemplateArg {
-  enum {
-    TypeArg,
-    ExprArg
-  } Kind;
-
-  uintptr_t Ptr;
-
-public:
-  explicit TemplateArg(QualType Type) 
-    : Kind(TypeArg), Ptr(reinterpret_cast<uintptr_t>(Type.getAsOpaquePtr())) { }
-  explicit TemplateArg(Expr *E)
-    : Kind(ExprArg), Ptr(reinterpret_cast<uintptr_t>(E)) { }
-
-  QualType getAsType() const {
-    if (Kind == TypeArg) 
-      return QualType::getFromOpaquePtr(reinterpret_cast<void*>(Ptr));
-    return QualType();
-  }
-
-  Expr *getAsExpr() const {
-    if (Kind == ExprArg) return reinterpret_cast<Expr *>(Ptr);
-    return 0;
-  }
-
-  void Destroy(ASTContext &C);
-};
-
-
 } /* end of namespace clang */
 
 #endif
index 8b9826e347fd901ad89d6f5b9f7fa6e9c37e5283..1d59489864f88b87e332e669eb750cc9caa7b665 100644 (file)
@@ -1440,6 +1440,8 @@ class ClassTemplateSpecializationType
   static void 
   packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words);
   
+  virtual void Destroy(ASTContext& C);
+
   friend class ASTContext;  // ASTContext creates these
 
 public:
index b13b8ef2288fc5e0c1545ef29e04367a49d51cda..14b2cea81af36b8d260690eac13175cd4fdd4b42 100644 (file)
@@ -74,7 +74,6 @@ public:
   typedef void MemInitTy;
   typedef void CXXScopeTy;
   typedef void TemplateParamsTy;
-  typedef void TemplateArgTy;
 
   /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
   /// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and
@@ -88,8 +87,6 @@ public:
   /// Same, but with ownership.
   typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
   typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult;
-  typedef ASTOwningResult<&ActionBase::DeleteTemplateArg> 
-    OwningTemplateArgResult;
   // Note that these will replace ExprResult and StmtResult when the transition
   // is complete.
 
@@ -97,38 +94,26 @@ public:
 #if !defined(DISABLE_SMART_POINTERS)
   typedef ASTOwningResult<&ActionBase::DeleteExpr> ExprArg;
   typedef ASTOwningResult<&ActionBase::DeleteStmt> StmtArg;
-  typedef ASTOwningResult<&ActionBase::DeleteTemplateArg> TemplateArgArg;
 #else
   typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg;
   typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg;
-  typedef ASTOwningPtr<&ActionBase::DeleteTemplateArg> TemplateArgArg;
 #endif
 
   /// Multiple expressions or statements as arguments.
   typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
   typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
   typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg;
-  typedef ASTMultiPtr<&ActionBase::DeleteTemplateArg> MultiTemplateArgsArg;
 
   // Utilities for Action implementations to return smart results.
 
   OwningExprResult ExprError() { return OwningExprResult(*this, true); }
   OwningStmtResult StmtError() { return OwningStmtResult(*this, true); }
-  OwningTemplateArgResult TemplateArgError() { 
-    return OwningTemplateArgResult(*this, true); 
-  }
 
   OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
   OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
-  OwningTemplateArgResult TemplateArgError(const DiagnosticBuilder&) {
-    return TemplateArgError();
-  }
 
   OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); }
   OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); }
-  OwningTemplateArgResult TemplateArgEmpty() { 
-    return OwningTemplateArgResult(*this, false); 
-  }
 
   /// Statistics.
   virtual void PrintStats() const {}
@@ -1126,14 +1111,6 @@ public:
     return 0;
   }
 
-  virtual OwningTemplateArgResult ActOnTypeTemplateArgument(TypeTy *Type) {
-    return TemplateArgError();
-  }
-
-  virtual OwningTemplateArgResult ActOnExprTemplateArgument(ExprArg Value) {
-    return TemplateArgError();
-  }
-
   /// \brief Process the declaration or definition of a class template
   /// with the given template parameter lists.
   virtual DeclTy *
@@ -1158,7 +1135,7 @@ public:
   virtual TypeTy * 
   ActOnClassTemplateSpecialization(DeclTy *Template,
                                    SourceLocation LAngleLoc,
-                                   MultiTemplateArgsArg TemplateArgs,
+                                   ASTTemplateArgsPtr TemplateArgs,
                                    SourceLocation RAngleLoc,
                                    const CXXScopeSpec *SS = 0) {
     return 0;
index 6017db761f95a3c4131a612424c19c20077a73e9..f191d9a3b40f0b20863cecc34533fe4c7c03619f 100644 (file)
@@ -132,7 +132,6 @@ namespace clang
     typedef void ExprTy;
     typedef void StmtTy;
     typedef void TemplateParamsTy;
-    typedef void TemplateArgTy;
 
     /// ActionResult - This structure is used while parsing/acting on
     /// expressions, stmts, etc.  It encapsulates both the object returned by
@@ -207,7 +206,6 @@ namespace clang
     virtual void DeleteExpr(ExprTy *E) {}
     virtual void DeleteStmt(StmtTy *E) {}
     virtual void DeleteTemplateParams(TemplateParamsTy *E) {}
-    virtual void DeleteTemplateArg(TemplateArgTy *E) {}
   };
 
   /// ASTDestroyer - The type of an AST node destruction function pointer.
@@ -222,10 +220,6 @@ namespace clang
   template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
     static const unsigned UID = 1;
   };
-  template <> struct DestroyerToUID<&ActionBase::DeleteTemplateArg> {
-    static const unsigned UID = 5; // FIXME
-  };
-
   /// ASTOwningResult - A moveable smart pointer for AST nodes that also
   /// has an extra flag to indicate an additional success status.
   template <ASTDestroyer Destroyer> class ASTOwningResult;
@@ -536,6 +530,62 @@ namespace clang
     }
 #endif
   };
+  
+  class ASTTemplateArgsPtr {
+#if !defined(DISABLE_SMART_POINTERS)
+    ActionBase &Actions;
+#endif
+    void **Args;
+    bool *ArgIsType;
+    mutable unsigned Count;
+
+#if !defined(DISABLE_SMART_POINTERS)
+    void destroy() {
+      if (!Count)
+        return;
+
+      for (unsigned i = 0; i != Count; ++i)
+        if (Args[i] && !ArgIsType[i])
+          Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]);
+
+      Count = 0;
+    }
+#endif
+
+  public:
+    ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType,
+                       unsigned count) : 
+#if !defined(DISABLE_SMART_POINTERS)
+      Actions(actions), 
+#endif
+      Args(args), ArgIsType(argIsType), Count(count) { }
+
+    // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+    ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : 
+#if !defined(DISABLE_SMART_POINTERS)
+      Actions(Other.Actions), 
+#endif
+      Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) {
+#if !defined(DISABLE_SMART_POINTERS)
+      Other.destroy();
+#endif
+    }
+
+#if !defined(DISABLE_SMART_POINTERS)
+    ~ASTTemplateArgsPtr() { destroy(); }
+#endif
+
+    void **getArgs() const { return Args; }
+    bool *getArgIsType() const {return ArgIsType; }
+    unsigned size() const { return Count; }
+
+    void **release() const { 
+#if !defined(DISABLE_SMART_POINTERS)
+      Count = 0;
+#endif
+      return Args;
+    }
+  };
 
 #if !defined(DISABLE_SMART_POINTERS)
 
index 7a73fcba53a1e8660f8d38c8703a977d448296b2..a197f2c0353b4b14a412d9c8b51ab5ae1506f2b5 100644 (file)
@@ -114,7 +114,6 @@ public:
   typedef Action::MemInitTy MemInitTy;
   typedef Action::CXXScopeTy CXXScopeTy;
   typedef Action::TemplateParamsTy TemplateParamsTy;
-  typedef Action::TemplateArgTy TemplateArgTy;
 
   typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists;
 
@@ -125,7 +124,6 @@ public:
 
   typedef Action::OwningExprResult OwningExprResult;
   typedef Action::OwningStmtResult OwningStmtResult;
-  typedef Action::OwningTemplateArgResult OwningTemplateArgResult;
 
   typedef Action::ExprArg ExprArg;
   typedef Action::MultiStmtArg MultiStmtArg;
@@ -141,15 +139,9 @@ public:
 
   OwningExprResult ExprError() { return OwningExprResult(Actions, true); }
   OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); }
-  OwningTemplateArgResult TemplateArgError() { 
-    return OwningTemplateArgResult(Actions, true); 
-  }
 
   OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
   OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
-  OwningTemplateArgResult TemplateArgError(const DiagnosticBuilder &) {
-    return TemplateArgError();
-  }
 
   // Parsing methods.
   
@@ -1029,11 +1021,13 @@ private:
   DeclTy *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
   DeclTy *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
   // C++ 14.3: Template arguments [temp.arg]
-  typedef llvm::SmallVector<TemplateArgTy*, 8> TemplateArgList;
+  typedef llvm::SmallVector<void *, 16> TemplateArgList;
+  typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList;
   void AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
                                const CXXScopeSpec *SS = 0);
-  bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
-  OwningTemplateArgResult ParseTemplateArgument();
+  bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
+                                 TemplateArgIsTypeList &TemplateArgIsType);
+  void *ParseTemplateArgument(bool &ArgIsType);
 
   //===--------------------------------------------------------------------===//
   // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
index ab5a3bc0b2f35ea2085bd72e2379b1203119cfd3..4eb866d6887b7e6a50d7fca42eed0cce59e26299 100644 (file)
@@ -44,11 +44,6 @@ TemplateParameterList::Create(ASTContext &C, SourceLocation TemplateLoc,
                                          NumParams, RAngleLoc);
 }
 
-void TemplateArg::Destroy(ASTContext &C) {
-  if (Kind == ExprArg)
-    getAsExpr()->Destroy(C);
-}
-
 //===----------------------------------------------------------------------===//
 // TemplateDecl Implementation
 //===----------------------------------------------------------------------===//
index 6ec5062f93a75d20922924138b0962977758672e..bf10b9ad70c695feee7a9bd60bf831ae2b108489 100644 (file)
@@ -925,6 +925,12 @@ ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs,
     Data[Arg] = Args[Arg];
 }
 
+void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+    if (!isArgType(Arg))
+      getArgAsExpr(Arg)->Destroy(C);
+}
+
 uintptr_t
 ClassTemplateSpecializationType::getArgAsOpaqueValue(unsigned Arg) const {
   const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
index 2e2cf5357f82d448beef5c1b3048f136d22685b3..f083be56024c3882532b3a009272c8a5454f0675 100644 (file)
@@ -368,10 +368,12 @@ void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
   SourceLocation LAngleLoc = ConsumeToken();
 
   // Parse the optional template-argument-list.
-  ASTVector<&ActionBase::DeleteTemplateArg, 8> TemplateArgs(Actions);
+  TemplateArgList TemplateArgs;
+  TemplateArgIsTypeList TemplateArgIsType;
   {
     MakeGreaterThanTemplateArgumentListTerminator G(GreaterThanIsOperator);
-    if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) {
+    if (Tok.isNot(tok::greater) && 
+        ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType)) {
       // Try to find the closing '>'.
       SkipUntil(tok::greater, true, true);
       
@@ -391,16 +393,15 @@ void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
   if (TNK == Action::TNK_Function_template) {
     // This is a function template. We'll be building a template-id
     // annotation token.
-    TemplateArgs.take(); // Annotation token takes ownership
     Tok.setKind(tok::annot_template_id);    
     TemplateIdAnnotation *TemplateId 
       = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) + 
-                                  sizeof(TemplateArgTy*) * TemplateArgs.size());
+                                  sizeof(void*) * TemplateArgs.size());
     TemplateId->TemplateNameLoc = TemplateNameLoc;
     TemplateId->Template = Template;
     TemplateId->LAngleLoc = LAngleLoc;
     TemplateId->NumArgs = TemplateArgs.size();
-    TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1);
+    void **Args = (void**)(TemplateId + 1);
     for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
       Args[Arg] = TemplateArgs[Arg];
     Tok.setAnnotationValue(TemplateId);
@@ -408,9 +409,12 @@ void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
     // This is a type template, e.g., a class template, template
     // template parameter, or template alias. We'll be building a
     // "typename" annotation token.
+    ASTTemplateArgsPtr TemplateArgsPtr(Actions, &TemplateArgs[0],
+                                       &TemplateArgIsType[0],
+                                       TemplateArgs.size());
     TypeTy *Ty 
-      = Actions.ActOnClassTemplateSpecialization(Template,LAngleLoc,
-                                                 move_arg(TemplateArgs),
+      = Actions.ActOnClassTemplateSpecialization(Template, LAngleLoc,
+                                                 TemplateArgsPtr,
                                                  RAngleLoc, SS);
     Tok.setKind(tok::annot_typename);
     Tok.setAnnotationValue(Ty);
@@ -433,7 +437,7 @@ void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
 ///         assignment-expression
 ///         type-id
 ///         id-expression
-Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
+void *Parser::ParseTemplateArgument(bool &ArgIsType) {
   // C++ [temp.arg]p2:
   //   In a template-argument, an ambiguity between a type-id and an
   //   expression is resolved to a type-id, regardless of the form of
@@ -441,15 +445,16 @@ Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
   //
   // Therefore, we initially try to parse a type-id.
   if (isTypeIdInParens()) {
-    TypeTy *TypeArg = ParseTypeName();
-    return Actions.ActOnTypeTemplateArgument(TypeArg);
+    ArgIsType = true;
+    return ParseTypeName();
   }
 
   OwningExprResult ExprArg = ParseExpression();
   if (ExprArg.isInvalid())
-    return TemplateArgError();
+    return 0;
 
-  return Actions.ActOnExprTemplateArgument(move(ExprArg));
+  ArgIsType = false;
+  return ExprArg.release();
 }
 
 /// ParseTemplateArgumentList - Parse a C++ template-argument-list
@@ -458,16 +463,20 @@ Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
 ///       template-argument-list: [C++ 14.2]
 ///         template-argument
 ///         template-argument-list ',' template-argument
-bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
+bool 
+Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
+                                  TemplateArgIsTypeList &TemplateArgIsType) {
   while (true) {
-    OwningTemplateArgResult Arg = ParseTemplateArgument();
-    if (Arg.isInvalid()) {
+    bool IsType = false;
+    void *Arg = ParseTemplateArgument(IsType);
+    if (Arg) {
+      TemplateArgs.push_back(Arg);
+      TemplateArgIsType.push_back(IsType);
+    } else {
       SkipUntil(tok::comma, tok::greater, true, true);
       return true;
     }
-    else
-      TemplateArgs.push_back(Arg.release());
-    
+
     // If the next token is a comma, consume it and keep reading
     // arguments.
     if (Tok.isNot(tok::comma)) break;
index bba99fd75131d546580f7736951029a6808aea89..ca4c528d986969ac6494f1032c5a52d2e598a043 100644 (file)
@@ -62,7 +62,6 @@ namespace clang {
   class TypedefDecl;
   class TemplateDecl;
   class TemplateParameterList;
-  class TemplateArg;
   class ObjCInterfaceDecl;
   class ObjCCompatibleAliasDecl;
   class ObjCProtocolDecl;
@@ -259,9 +258,6 @@ public:
     return OwningExprResult(*this, R.get());
   }
   OwningStmtResult Owned(Stmt* S) { return OwningStmtResult(*this, S); }
-  OwningTemplateArgResult Owned(TemplateArg *Arg) { 
-    return OwningTemplateArgResult(*this, Arg);
-  }
 
   virtual void ActOnEndOfTranslationUnit();
 
@@ -1511,10 +1507,6 @@ public:
                              DeclTy **Params, unsigned NumParams,
                              SourceLocation RAngleLoc);
   
-  virtual OwningTemplateArgResult ActOnTypeTemplateArgument(TypeTy *Type);
-
-  virtual OwningTemplateArgResult ActOnExprTemplateArgument(ExprArg Value);
-
   virtual DeclTy *
   ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
                      SourceLocation KWLoc, const CXXScopeSpec &SS,
@@ -1525,7 +1517,7 @@ public:
   virtual TypeTy * 
   ActOnClassTemplateSpecialization(DeclTy *Template,
                                    SourceLocation LAngleLoc,
-                                   MultiTemplateArgsArg TemplateArgs,
+                                   ASTTemplateArgsPtr TemplateArgs,
                                    SourceLocation RAngleLoc,
                                    const CXXScopeSpec *SS = 0);
 
index 6b6a50130abfcfb6dea01c9daf99a7eaa0b42a58..740198b11bd327710dbd73b6bda202a7f5d2521e 100644 (file)
@@ -231,15 +231,6 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
                                        (Decl**)Params, NumParams, RAngleLoc);
 }
 
-Sema::OwningTemplateArgResult Sema::ActOnTypeTemplateArgument(TypeTy *Type) {
-  return Owned(new (Context) TemplateArg(QualType::getFromOpaquePtr(Type)));
-}
-
-Sema::OwningTemplateArgResult 
-Sema::ActOnExprTemplateArgument(ExprArg Value) {
-  return Owned(new (Context) TemplateArg(static_cast<Expr *>(Value.release())));
-}
-
 Sema::DeclTy *
 Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
                          SourceLocation KWLoc, const CXXScopeSpec &SS,
@@ -368,37 +359,21 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
 Action::TypeTy * 
 Sema::ActOnClassTemplateSpecialization(DeclTy *TemplateD,
                                        SourceLocation LAngleLoc,
-                                       MultiTemplateArgsArg TemplateArgsIn,
+                                       ASTTemplateArgsPtr TemplateArgs,
                                        SourceLocation RAngleLoc,
                                        const CXXScopeSpec *SS) {
   TemplateDecl *Template = cast<TemplateDecl>(static_cast<Decl *>(TemplateD));
 
-  // FIXME: Not happy about this. We should teach the parser to pass
-  // us opaque pointers + bools for template argument lists.
-  // FIXME: Also not happy about the fact that we leak these
-  // TemplateArg structures. Fixing the above will fix this, too.
-  llvm::SmallVector<uintptr_t, 16> Args;
-  llvm::SmallVector<bool, 16> ArgIsType;
-  unsigned NumArgs = TemplateArgsIn.size();
-  TemplateArg **TemplateArgs 
-    = reinterpret_cast<TemplateArg **>(TemplateArgsIn.release());
-  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
-    if (Expr *ExprArg = TemplateArgs[Arg]->getAsExpr()) {
-      Args.push_back(reinterpret_cast<uintptr_t>(ExprArg));
-      ArgIsType.push_back(false);
-    } else {
-      QualType T = TemplateArgs[Arg]->getAsType();
-      Args.push_back(reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()));
-      ArgIsType.push_back(true);
-    }
-  }
-
   // Yes, all class template specializations are just silly sugar for
   // 'int'. Gotta problem wit dat?
-  return Context.getClassTemplateSpecializationType(Template, NumArgs,
-                                                    &Args[0], &ArgIsType[0],
-                                                    Context.IntTy)
-    .getAsOpaquePtr();
+  QualType Result
+    = Context.getClassTemplateSpecializationType(Template, 
+                                                 TemplateArgs.size(),
+                    reinterpret_cast<uintptr_t *>(TemplateArgs.getArgs()), 
+                                                 TemplateArgs.getArgIsType(),
+                                                 Context.IntTy);
+  TemplateArgs.release();
+  return Result.getAsOpaquePtr();
 }
 
 /// \brief Determine whether the given template parameter lists are