//===--- ParsedTemplate.h - Template Parsing Data Types -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file provides data structures that store the parsed representation of
//  templates.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H

#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Ownership.h"
#include <cassert>

namespace clang {  
  /// \brief Represents the parsed form of a C++ template argument.
  class ParsedTemplateArgument {
  public:
    /// \brief Describes the kind of template argument that was parsed.
    enum KindType {
      /// \brief A template type parameter, stored as a type.
      Type,
      /// \brief A non-type template parameter, stored as an expression.
      NonType,
      /// \brief A template template argument, stored as a template name.
      Template
    };

    /// \brief Build an empty template argument. 
    ///
    /// This template argument is invalid.
    ParsedTemplateArgument() : Kind(Type), Arg(0) { }
    
    /// \brief Create a template type argument or non-type template argument.
    ///
    /// \param Arg the template type argument or non-type template argument.
    /// \param Loc the location of the type.
    ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
      : Kind(Kind), Arg(Arg), Loc(Loc) { }
    
    /// \brief Create a template template argument.
    ///
    /// \param SS the C++ scope specifier that precedes the template name, if
    /// any.
    ///
    /// \param Template the template to which this template template 
    /// argument refers.
    ///
    /// \param TemplateLoc the location of the template name.
    ParsedTemplateArgument(const CXXScopeSpec &SS,
                           ParsedTemplateTy Template, 
                           SourceLocation TemplateLoc) 
      : Kind(ParsedTemplateArgument::Template),
        Arg(Template.getAsOpaquePtr()), 
        Loc(TemplateLoc), SS(SS), EllipsisLoc() { }
    
    /// \brief Determine whether the given template argument is invalid.
    bool isInvalid() const { return Arg == 0; }
    
    /// \brief Determine what kind of template argument we have.
    KindType getKind() const { return Kind; }
    
    /// \brief Retrieve the template type argument's type.
    ParsedType getAsType() const {
      assert(Kind == Type && "Not a template type argument");
      return ParsedType::getFromOpaquePtr(Arg);
    }
    
    /// \brief Retrieve the non-type template argument's expression.
    Expr *getAsExpr() const {
      assert(Kind == NonType && "Not a non-type template argument");
      return static_cast<Expr*>(Arg);
    }
    
    /// \brief Retrieve the template template argument's template name.
    ParsedTemplateTy getAsTemplate() const {
      assert(Kind == Template && "Not a template template argument");
      return ParsedTemplateTy::getFromOpaquePtr(Arg);
    }
    
    /// \brief Retrieve the location of the template argument.
    SourceLocation getLocation() const { return Loc; }
    
    /// \brief Retrieve the nested-name-specifier that precedes the template
    /// name in a template template argument.
    const CXXScopeSpec &getScopeSpec() const {
      assert(Kind == Template && 
             "Only template template arguments can have a scope specifier");
      return SS;
    }
    
    /// \brief Retrieve the location of the ellipsis that makes a template
    /// template argument into a pack expansion.
    SourceLocation getEllipsisLoc() const {
      assert(Kind == Template && 
             "Only template template arguments can have an ellipsis");
      return EllipsisLoc;
    }
    
    /// \brief Retrieve a pack expansion of the given template template
    /// argument.
    ///
    /// \param EllipsisLoc The location of the ellipsis.
    ParsedTemplateArgument getTemplatePackExpansion(
                                              SourceLocation EllipsisLoc) const;
    
  private:
    KindType Kind;
    
    /// \brief The actual template argument representation, which may be
    /// an \c ActionBase::TypeTy* (for a type), an Expr* (for an
    /// expression), or an ActionBase::TemplateTy (for a template).
    void *Arg;

    /// \brief the location of the template argument.
    SourceLocation Loc;
    
    /// \brief The nested-name-specifier that can accompany a template template
    /// argument.
    CXXScopeSpec SS;
    
    /// \brief The ellipsis location that can accompany a template template
    /// argument (turning it into a template template argument expansion).
    SourceLocation EllipsisLoc;
  };
  
  /// \brief Information about a template-id annotation
  /// token.
  ///
  /// A template-id annotation token contains the template declaration, 
  /// template arguments, whether those template arguments were types, 
  /// expressions, or template names, and the source locations for important 
  /// tokens. All of the information about template arguments is allocated 
  /// directly after this structure.
  struct TemplateIdAnnotation {
    /// \brief The nested-name-specifier that precedes the template name.
    CXXScopeSpec SS;

    /// TemplateKWLoc - The location of the template keyword within the
    /// source.
    SourceLocation TemplateKWLoc;

    /// TemplateNameLoc - The location of the template name within the
    /// source.
    SourceLocation TemplateNameLoc;
    
    /// FIXME: Temporarily stores the name of a specialization
    IdentifierInfo *Name;
    
    /// FIXME: Temporarily stores the overloaded operator kind.
    OverloadedOperatorKind Operator;
    
    /// The declaration of the template corresponding to the
    /// template-name.
    ParsedTemplateTy Template;
    
    /// The kind of template that Template refers to.
    TemplateNameKind Kind;
    
    /// The location of the '<' before the template argument
    /// list.
    SourceLocation LAngleLoc;
    
    /// The location of the '>' after the template argument
    /// list.
    SourceLocation RAngleLoc;
    
    /// NumArgs - The number of template arguments.
    unsigned NumArgs;
    
    /// \brief Retrieves a pointer to the template arguments
    ParsedTemplateArgument *getTemplateArgs() { 
      return reinterpret_cast<ParsedTemplateArgument *>(this + 1); 
    }

    /// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
    /// appends it to List.
    static TemplateIdAnnotation *
    Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
      TemplateIdAnnotation *TemplateId
        = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
                                      sizeof(ParsedTemplateArgument) * NumArgs);
      TemplateId->NumArgs = NumArgs;
      
      // Default-construct nested-name-specifier.
      new (&TemplateId->SS) CXXScopeSpec();
      
      // Default-construct parsed template arguments.
      ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs();
      for (unsigned I = 0; I != NumArgs; ++I)
        new (TemplateArgs + I) ParsedTemplateArgument();
      
      List.push_back(TemplateId);
      return TemplateId;
    }
    
    void Destroy() { 
      SS.~CXXScopeSpec();
      free(this); 
    }
  };

  /// Retrieves the range of the given template parameter lists.
  SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
                                     unsigned NumParams);  
  
  inline const ParsedTemplateArgument &
  ASTTemplateArgsPtr::operator[](unsigned Arg) const { 
    return Args[Arg]; 
  }
}

#endif
