//===--- 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(nullptr) { }
    
    /// \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()), 
        SS(SS), Loc(TemplateLoc), EllipsisLoc() { }
    
    /// \brief Determine whether the given template argument is invalid.
    bool isInvalid() const { return Arg == nullptr; }
    
    /// \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 nested-name-specifier that can accompany a template template
    /// argument.
    CXXScopeSpec SS;

    /// \brief the location of the template argument.
    SourceLocation Loc;

    /// \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);  
}

#endif
