[cfe-commits] r64153 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclTemplate.h include/clang/AST/Type.h include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/AST/ASTContext.cpp lib/AST/DeclTemplate.cpp lib/AST/Type.cpp lib/AST/TypeSerialization.cpp lib/CodeGen/CodeGenTypes.cpp lib/Parse/MinimalAction.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp test/SemaTemplate/class-template-id.cpp
Douglas Gregor
dgregor at apple.com
Mon Feb 9 10:46:08 PST 2009
Author: dgregor
Date: Mon Feb 9 12:46:07 2009
New Revision: 64153
URL: http://llvm.org/viewvc/llvm-project?rev=64153&view=rev
Log:
Start processing template-ids as types when the template-name refers
to a class template. For example, the template-id 'vector<int>' now
has a nice, sugary type in the type system. What we can do now:
- Parse template-ids like 'vector<int>' (where 'vector' names a
class template) and form proper types for them in the type system.
- Parse icky template-ids like 'A<5>' and 'A<(5 > 0)>' properly,
using (sadly) a bool in the parser to tell it whether '>' should
be treated as an operator or not.
This is a baby-step, with major problems and limitations:
- There are currently two ways that we handle template arguments
(whether they are types or expressions). These will be merged, and,
most likely, TemplateArg will disappear.
- We don't have any notion of the declaration of class template
specializations or of template instantiations, so all template-ids
are fancy names for 'int' :)
Added:
cfe/trunk/test/SemaTemplate/class-template-id.cpp
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclTemplate.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/AST/TypeSerialization.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/Parse/MinimalAction.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Feb 9 12:46:07 2009
@@ -69,6 +69,8 @@
llvm::FoldingSet<FunctionTypeNoProto> FunctionTypeNoProtos;
llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
+ llvm::FoldingSet<ClassTemplateSpecializationType>
+ ClassTemplateSpecializationTypes;
llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
/// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
@@ -262,6 +264,11 @@
QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
IdentifierInfo *Name = 0);
+ QualType getClassTemplateSpecializationType(TemplateDecl *Template,
+ unsigned NumArgs,
+ uintptr_t *Args, bool *ArgIsType,
+ QualType Canon);
+
/// getObjCQualifiedInterfaceType - Return a
/// ObjCQualifiedInterfaceType type for the given interface decl and
/// the conforming protocol list.
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Mon Feb 9 12:46:07 2009
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
#define LLVM_CLANG_AST_DECLTEMPLATE_H
+#include "clang/AST/DeclCXX.h"
+
namespace clang {
class TemplateParameterList;
@@ -158,7 +160,7 @@
public:
/// Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
- return static_cast<CXXRecordDecl*>(TemplatedDecl);
+ return static_cast<CXXRecordDecl *>(TemplatedDecl);
}
/// Create a class teplate node.
@@ -334,6 +336,35 @@
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
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Feb 9 12:46:07 2009
@@ -30,6 +30,7 @@
class ASTContext;
class Type;
class TypedefDecl;
+ class TemplateDecl;
class TemplateTypeParmDecl;
class NonTypeTemplateParmDecl;
class TemplateTemplateParamDecl;
@@ -69,6 +70,7 @@
class ObjCQualifiedIdType;
class ObjCQualifiedInterfaceType;
class StmtIteratorBase;
+ class ClassTemplateSpecializationType;
/// QualType - For efficiency, we don't store CVR-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
@@ -245,7 +247,7 @@
Vector, ExtVector,
FunctionNoProto, FunctionProto,
TypeName, Tagged, ASQual,
- TemplateTypeParm,
+ TemplateTypeParm, ClassTemplateSpecialization,
ObjCInterface, ObjCQualifiedInterface,
ObjCQualifiedId,
TypeOfExp, TypeOfTyp, // GNU typeof extension.
@@ -391,6 +393,9 @@
const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
const TemplateTypeParmType *getAsTemplateTypeParmType() const;
+ const ClassTemplateSpecializationType *
+ getClassTemplateSpecializationType() const;
+
/// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC
/// interface, return the interface type, otherwise return null.
const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const;
@@ -400,8 +405,6 @@
/// This method should never be used when type qualifiers are meaningful.
const Type *getArrayElementTypeNoTypeQual() const;
-
-
/// getDesugaredType - Return the specified type with any "sugar" removed from
/// the type. This takes off typedefs, typeof's etc. If the outer level of
/// the type is already concrete, it returns it unmodified. This is similar
@@ -1395,6 +1398,127 @@
friend class Type;
};
+/// \brief Represents the type of a class template specialization as
+/// written in the source code.
+///
+/// Class template specialization types represent the syntactic form
+/// of a template-id that refers to a type, e.g., @c vector<int>. All
+/// class template specialization types are syntactic sugar, whose
+/// canonical type will point to some other type node that represents
+/// the instantiation or class template specialization. For example, a
+/// class template specialization type of @c vector<int> will refer to
+/// a tag type for the instantiation
+/// @c std::vector<int, std::allocator<int>>.
+class ClassTemplateSpecializationType
+ : public Type, public llvm::FoldingSetNode {
+
+ // FIXME: Do we want templates to have a representation in the type
+ // system? It will probably help with dependent templates and
+ // possibly with template-names preceded by a nested-name-specifier.
+ TemplateDecl *Template;
+
+ unsigned NumArgs;
+
+ ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs,
+ uintptr_t *Args, bool *ArgIsType,
+ QualType Canon);
+
+ /// \brief Retrieve the number of packed words that precede the
+ /// actual arguments.
+ ///
+ /// The flags that specify whether each argument is a type or an
+ /// expression are packed into the
+ /// ClassTemplateSpecializationType. This routine computes the
+ /// number of pointer-sized words we need to store this information,
+ /// based on the number of template arguments
+ static unsigned getNumPackedWords(unsigned NumArgs) {
+ const unsigned BitsPerWord = sizeof(uintptr_t) * CHAR_BIT;
+ return NumArgs / BitsPerWord + (NumArgs % BitsPerWord > 0);
+ }
+
+ /// \brief Pack the given boolean values into words.
+ static void
+ packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words);
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Retrieve the template that we are specializing.
+ TemplateDecl *getTemplate() const { return Template; }
+
+ /// \briefe Retrieve the number of template arguments.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// \brief Retrieve a specific template argument as a type.
+ /// \precondition @c isArgType(Arg)
+ QualType getArgAsType(unsigned Arg) const {
+ assert(isArgType(Arg) && "Argument is not a type");
+ return QualType::getFromOpaquePtr(
+ reinterpret_cast<void *>(getArgAsOpaqueValue(Arg)));
+ }
+
+ /// \brief Retrieve a specific template argument as an expression.
+ /// \precondition @c !isArgType(Arg)
+ Expr *getArgAsExpr(unsigned Arg) const {
+ assert(!isArgType(Arg) && "Argument is not an expression");
+ return reinterpret_cast<Expr *>(getArgAsOpaqueValue(Arg));
+ }
+
+ /// \brief Retrieve the specified template argument as an opaque value.
+ uintptr_t getArgAsOpaqueValue(unsigned Arg) const;
+
+ /// \brief Determine whether the given template argument is a type.
+ bool isArgType(unsigned Arg) const;
+
+ virtual void getAsStringInternal(std::string &InnerString) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ // Add the template
+ ID.AddPointer(Template);
+
+ // Add the packed words describing what kind of template arguments
+ // we have.
+ uintptr_t *Data = reinterpret_cast<uintptr_t *>(this + 1);
+ for (unsigned Packed = 0, NumPacked = getNumPackedWords(NumArgs);
+ Packed != NumPacked; ++Packed)
+ ID.AddInteger(Data[Packed]);
+
+ // Add the template arguments themselves.
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+ ID.AddInteger(getArgAsOpaqueValue(Arg));
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, TemplateDecl *T,
+ unsigned NumArgs, uintptr_t *Args, bool *ArgIsType) {
+ // Add the template
+ ID.AddPointer(T);
+
+ // Add the packed words describing what kind of template arguments
+ // we have.
+ unsigned NumPackedWords = getNumPackedWords(NumArgs);
+ unsigned NumPackedBytes = NumPackedWords * sizeof(uintptr_t);
+ uintptr_t *PackedWords
+ = reinterpret_cast<uintptr_t *>(alloca(NumPackedBytes));
+ packBooleanValues(NumArgs, ArgIsType, PackedWords);
+ for (unsigned Packed = 0; Packed != NumPackedWords; ++Packed)
+ ID.AddInteger(PackedWords[Packed]);
+
+ // Add the template arguments themselves.
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+ ID.AddInteger(Args[Arg]);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ClassTemplateSpecialization;
+ }
+ static bool classof(const ClassTemplateSpecializationType *T) { return true; }
+
+protected:
+ virtual void EmitImpl(llvm::Serializer& S) const;
+ static Type* CreateImpl(ASTContext& Context, llvm::Deserializer& D);
+ friend class Type;
+};
+
/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
/// object oriented design. They basically correspond to C++ classes. There
/// are two kinds of interface types, normal interfaces like "NSString" and
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Feb 9 12:46:07 2009
@@ -108,7 +108,7 @@
typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg;
- typedef ASTMultiPtr<&ActionBase::DeleteTemplateArg> MultiTemplateArgArg;
+ typedef ASTMultiPtr<&ActionBase::DeleteTemplateArg> MultiTemplateArgsArg;
// Utilities for Action implementations to return smart results.
@@ -149,13 +149,28 @@
virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS = 0) = 0;
- /// isTemplateName - Determines whether the identifier II is a
- /// template name in the current scope, and returns the template
- /// declaration if II names a template. An optional CXXScope can be
- /// passed to indicate the C++ scope in which the identifier will be
- /// found.
- virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS = 0) = 0;
+ /// \brief Specifies the kind of template name. Returned from
+ /// isTemplateName.
+ enum TemplateNameKind {
+ /// The name does not refer to a template.
+ TNK_Non_template,
+ /// The name refers to a function template or a set of overloaded
+ /// functions that includes at least one function template.
+ TNK_Function_template,
+ /// The name refers to a class template.
+ TNK_Class_template,
+ /// The name referes to a template template parameter.
+ TNK_Template_template_parm
+ };
+
+ /// \brief Determines whether the identifier II is a template name
+ /// in the current scope. If so, the kind of template name is
+ /// returned, and \p TemplateDecl receives the declaration. An
+ /// optional CXXScope can be passed to indicate the C++ scope in
+ /// which the identifier will be found.
+ virtual TemplateNameKind isTemplateName(IdentifierInfo &II, Scope *S,
+ DeclTy *&TemplateDecl,
+ const CXXScopeSpec *SS = 0) = 0;
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
/// global scope ('::').
@@ -1111,8 +1126,16 @@
return 0;
}
- // \brief Process the declaration or definition of a class template
- // with the given template parameter lists.
+ 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 *
ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
@@ -1122,7 +1145,25 @@
return 0;
}
-
+ /// \brief Form a class template specialization from a template and
+ /// a list of template arguments.
+ ///
+ /// \param Template A template whose specialization results in a
+ /// type, e.g., a class template or template template parameter.
+ ///
+ /// \todo "Class template specialization" is the standard term for
+ /// the types that we're forming, but the name
+ /// ActOnClassTemplateSpecialization sounds like we're declaring a
+ /// new class template specialization.
+ virtual TypeTy *
+ ActOnClassTemplateSpecialization(DeclTy *Template,
+ SourceLocation LAngleLoc,
+ MultiTemplateArgsArg TemplateArgs,
+ SourceLocation RAngleLoc,
+ const CXXScopeSpec *SS = 0) {
+ return 0;
+ };
+
//===----------------------- Obj-C Declarations -------------------------===//
// ActOnStartClassInterface - this action is called immediately after parsing
@@ -1372,13 +1413,9 @@
virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S,
const CXXScopeSpec *SS);
- /// isTemplateName - Determines whether the identifier II is a
- /// template name in the current scope, and returns the template
- /// declaration if II names a template. An optional CXXScope can be
- /// passed to indicate the C++ scope in which the identifier will be
- /// found.
- virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS = 0);
+ virtual TemplateNameKind isTemplateName(IdentifierInfo &II, Scope *S,
+ DeclTy *&TemplateDecl,
+ const CXXScopeSpec *SS = 0);
/// ActOnDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Feb 9 12:46:07 2009
@@ -58,6 +58,44 @@
PragmaHandler *PackHandler;
+ /// Whether the '>' token acts as an operator or not. This will be
+ /// true except when we are parsing an expression within a C++
+ /// template argument list, where the '>' closes the template
+ /// argument list.
+ bool GreaterThanIsOperator;
+
+ /// \brief RAII object that makes '>' behave like the closing angle
+ /// bracket for a template argument list.
+ struct MakeGreaterThanTemplateArgumentListTerminator {
+ bool &GreaterThanIsOperator;
+ bool OldGreaterThanIsOperator;
+
+ MakeGreaterThanTemplateArgumentListTerminator(bool >IO)
+ : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
+ GTIO = false;
+ }
+
+ ~MakeGreaterThanTemplateArgumentListTerminator() {
+ GreaterThanIsOperator = OldGreaterThanIsOperator;
+ }
+ };
+
+ /// \brief RAII object that makes '>' behave like an
+ /// operator. Occurs, for example, inside parentheses.
+ struct MakeGreaterThanAnOperator {
+ bool &GreaterThanIsOperator;
+ bool OldGreaterThanIsOperator;
+
+ MakeGreaterThanAnOperator(bool >IO)
+ : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
+ GTIO = true;
+ }
+
+ ~MakeGreaterThanAnOperator() {
+ GreaterThanIsOperator = OldGreaterThanIsOperator;
+ }
+ };
+
public:
Parser(Preprocessor &PP, Action &Actions);
~Parser();
@@ -976,6 +1014,7 @@
//===--------------------------------------------------------------------===//
// C++ 14: Templates [temp]
typedef llvm::SmallVector<DeclTy *, 4> TemplateParameterList;
+ typedef Action::TemplateNameKind TemplateNameKind;
// C++ 14.1: Template Parameters [temp.param]
DeclTy *ParseTemplateDeclaration(unsigned Context);
@@ -991,7 +1030,8 @@
DeclTy *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
// C++ 14.3: Template arguments [temp.arg]
typedef llvm::SmallVector<TemplateArgTy*, 8> TemplateArgList;
- void AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS = 0);
+ void AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
+ const CXXScopeSpec *SS = 0);
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
OwningTemplateArgResult ParseTemplateArgument();
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Feb 9 12:46:07 2009
@@ -1220,6 +1220,34 @@
return QualType(TypeParm, 0);
}
+QualType
+ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
+ unsigned NumArgs,
+ uintptr_t *Args, bool *ArgIsType,
+ QualType Canon) {
+ llvm::FoldingSetNodeID ID;
+ ClassTemplateSpecializationType::Profile(ID, Template, NumArgs, Args,
+ ArgIsType);
+ void *InsertPos = 0;
+ ClassTemplateSpecializationType *Spec
+ = ClassTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (Spec)
+ return QualType(Spec, 0);
+
+ void *Mem = Allocate(sizeof(ClassTemplateSpecializationType) +
+ (sizeof(uintptr_t) *
+ (ClassTemplateSpecializationType::
+ getNumPackedWords(NumArgs) +
+ NumArgs)), 8);
+ Spec = new (Mem) ClassTemplateSpecializationType(Template, NumArgs, Args,
+ ArgIsType, Canon);
+ Types.push_back(Spec);
+ ClassTemplateSpecializationTypes.InsertNode(Spec, InsertPos);
+
+ return QualType(Spec, 0);
+}
+
/// CmpProtocolNames - Comparison predicate for sorting protocols
/// alphabetically.
static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Mon Feb 9 12:46:07 2009
@@ -13,6 +13,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/STLExtras.h"
@@ -43,6 +44,11 @@
NumParams, RAngleLoc);
}
+void TemplateArg::Destroy(ASTContext &C) {
+ if (Kind == ExprArg)
+ getAsExpr()->Destroy(C);
+}
+
//===----------------------------------------------------------------------===//
// TemplateDecl Implementation
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Mon Feb 9 12:46:07 2009
@@ -489,6 +489,14 @@
return dyn_cast<TemplateTypeParmType>(CanonicalType);
}
+const ClassTemplateSpecializationType *
+Type::getClassTemplateSpecializationType() const {
+ // There is no sugar for class template specialization types, so
+ // just return the canonical type pointer if it is the right class.
+ return dyn_cast<ClassTemplateSpecializationType>(CanonicalType);
+}
+
+
bool Type::isIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
@@ -882,6 +890,54 @@
return isa<EnumDecl>(TT->getDecl());
}
+void
+ClassTemplateSpecializationType::
+packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words) {
+ const unsigned BitsPerWord = sizeof(uintptr_t) * CHAR_BIT;
+
+ for (unsigned PW = 0, NumPackedWords = getNumPackedWords(NumArgs), Arg = 0;
+ PW != NumPackedWords; ++PW) {
+ uintptr_t Word = 0;
+ for (unsigned Bit = 0; Bit < BitsPerWord && Arg < NumArgs; ++Bit, ++Arg) {
+ Word <<= 1;
+ Word |= Values[Arg];
+ }
+ Words[PW] = Word;
+ }
+}
+
+ClassTemplateSpecializationType::
+ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs,
+ uintptr_t *Args, bool *ArgIsType,
+ QualType Canon)
+ : Type(ClassTemplateSpecialization, Canon, /*FIXME:Dependent=*/false),
+ Template(T), NumArgs(NumArgs)
+{
+ uintptr_t *Data = reinterpret_cast<uintptr_t *>(this + 1);
+
+ // Pack the argument-is-type values into the words just after the
+ // class template specialization type.
+ packBooleanValues(NumArgs, ArgIsType, Data);
+
+ // Copy the template arguments after the packed words.
+ Data += getNumPackedWords(NumArgs);
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+ Data[Arg] = Args[Arg];
+}
+
+uintptr_t
+ClassTemplateSpecializationType::getArgAsOpaqueValue(unsigned Arg) const {
+ const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
+ Data += getNumPackedWords(NumArgs);
+ return Data[Arg];
+}
+
+bool ClassTemplateSpecializationType::isArgType(unsigned Arg) const {
+ const unsigned BitsPerWord = sizeof(uintptr_t) * CHAR_BIT;
+ const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
+ Data += Arg / BitsPerWord;
+ return (*Data >> (Arg % BitsPerWord)) & 0x01;
+}
//===----------------------------------------------------------------------===//
// Type Printing
@@ -1146,6 +1202,47 @@
InnerString = Name->getName() + InnerString;
}
+void
+ClassTemplateSpecializationType::
+getAsStringInternal(std::string &InnerString) const {
+ std::string SpecString = Template->getNameAsString();
+ SpecString += '<';
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (Arg)
+ SpecString += ", ";
+
+ // Print the argument into a string.
+ std::string ArgString;
+ if (isArgType(Arg))
+ getArgAsType(Arg).getAsStringInternal(ArgString);
+ else {
+ llvm::raw_string_ostream s(ArgString);
+ getArgAsExpr(Arg)->printPretty(s);
+ }
+
+ // If this is the first argument and its string representation
+ // begins with the global scope specifier ('::foo'), add a space
+ // to avoid printing the diagraph '<:'.
+ if (!Arg && !ArgString.empty() && ArgString[0] == ':')
+ SpecString += ' ';
+
+ SpecString += ArgString;
+ }
+
+ // If the last character of our string is '>', add another space to
+ // keep the two '>''s separate tokens. We don't *have* to do this in
+ // C++0x, but it's still good hygiene.
+ if (SpecString[SpecString.size() - 1] == '>')
+ SpecString += ' ';
+
+ SpecString += '>';
+
+ if (InnerString.empty())
+ InnerString.swap(SpecString);
+ else
+ InnerString = SpecString + ' ' + InnerString;
+}
+
void ObjCInterfaceType::getAsStringInternal(std::string &InnerString) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
Modified: cfe/trunk/lib/AST/TypeSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeSerialization.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypeSerialization.cpp (original)
+++ cfe/trunk/lib/AST/TypeSerialization.cpp Mon Feb 9 12:46:07 2009
@@ -13,6 +13,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ASTContext.h"
#include "llvm/Bitcode/Serialize.h"
@@ -377,6 +378,48 @@
}
//===----------------------------------------------------------------------===//
+// ClassTemplateSpecializationType
+//===----------------------------------------------------------------------===//
+
+void ClassTemplateSpecializationType::EmitImpl(Serializer& S) const {
+ S.Emit(getCanonicalTypeInternal());
+ S.EmitPtr(Template);
+ S.EmitInt(NumArgs);
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ S.EmitBool(isArgType(Arg));
+ if (isArgType(Arg))
+ S.Emit(getArgAsType(Arg));
+ else
+ S.EmitOwnedPtr(getArgAsExpr(Arg));
+ }
+}
+
+Type*
+ClassTemplateSpecializationType::
+CreateImpl(ASTContext& Context, Deserializer& D) {
+ llvm::SmallVector<uintptr_t, 16> Args;
+ llvm::SmallVector<bool, 16> ArgIsType;
+
+ QualType Canon = QualType::ReadVal(D);
+ TemplateDecl *Template = cast<TemplateDecl>(D.ReadPtr<Decl>());
+ unsigned NumArgs = D.ReadInt();
+
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ bool IsType = D.ReadBool();
+ ArgIsType.push_back(IsType);
+ if (IsType)
+ Args.push_back(
+ reinterpret_cast<uintptr_t>(QualType::ReadVal(D).getAsOpaquePtr()));
+ else
+ Args.push_back(reinterpret_cast<uintptr_t>(D.ReadOwnedPtr<Expr>(Context)));
+ }
+
+ return Context.getClassTemplateSpecializationType(Template, NumArgs,
+ &Args[0], &ArgIsType[0],
+ Canon).getTypePtr();
+}
+
+//===----------------------------------------------------------------------===//
// VariableArrayType
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Mon Feb 9 12:46:07 2009
@@ -176,6 +176,7 @@
switch (Ty.getTypeClass()) {
case Type::TypeName: // typedef isn't canonical.
case Type::TemplateTypeParm:// template type parameters never generated
+ case Type::ClassTemplateSpecialization: // these types are always sugar
case Type::DependentSizedArray: // dependent types are never generated
case Type::TypeOfExp: // typeof isn't canonical.
case Type::TypeOfTyp: // typeof isn't canonical.
Modified: cfe/trunk/lib/Parse/MinimalAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/MinimalAction.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/MinimalAction.cpp (original)
+++ cfe/trunk/lib/Parse/MinimalAction.cpp Mon Feb 9 12:46:07 2009
@@ -95,14 +95,11 @@
return false;
}
- /// isTemplateName - Determines whether the identifier II is a
- /// template name in the current scope, and returns the template
- /// declaration if II names a template. An optional CXXScope can be
- /// passed to indicate the C++ scope in which the identifier will be
- /// found.
-Action::DeclTy *MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS ) {
- return 0;
+Action::TemplateNameKind
+MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S,
+ DeclTy *&TemplateDecl,
+ const CXXScopeSpec *SS) {
+ return TNK_Non_template;
}
/// ActOnDeclarator - If this is a typedef declarator, we modify the
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Feb 9 12:46:07 2009
@@ -499,6 +499,7 @@
Token Next = NextToken();
TypeTy *TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
Next.getLocation(), CurScope, &SS);
+
if (TypeRep == 0)
goto DoneWithDeclSpec;
@@ -553,9 +554,23 @@
// It has to be available as a typedef too!
TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), CurScope);
+
+ if (TypeRep == 0 && getLang().CPlusPlus && NextToken().is(tok::less)) {
+ // If we have a template name, annotate the token and try again.
+ DeclTy *Template = 0;
+ if (TemplateNameKind TNK =
+ Actions.isTemplateName(*Tok.getIdentifierInfo(), CurScope,
+ Template)) {
+ AnnotateTemplateIdToken(Template, TNK, 0);
+ continue;
+ }
+ }
+
if (TypeRep == 0)
goto DoneWithDeclSpec;
+
+
// C++: If the identifier is actually the name of the class type
// being defined and the next token is a '(', then this is a
// constructor declaration. We're done with the decl-specifiers
@@ -1752,11 +1767,12 @@
// If this identifier is followed by a '<', we may have a template-id.
DeclTy *Template;
+ Action::TemplateNameKind TNK;
if (getLang().CPlusPlus && NextToken().is(tok::less) &&
- (Template = Actions.isTemplateName(*Tok.getIdentifierInfo(),
- CurScope))) {
+ (TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(),
+ CurScope, Template))) {
IdentifierInfo *II = Tok.getIdentifierInfo();
- AnnotateTemplateIdToken(Template, 0);
+ AnnotateTemplateIdToken(Template, TNK, 0);
// FIXME: Set the declarator to a template-id. How? I don't
// know... for now, just use the identifier.
D.SetIdentifier(II, Tok.getLocation());
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Feb 9 12:46:07 2009
@@ -55,8 +55,17 @@
/// getBinOpPrecedence - Return the precedence of the specified binary operator
/// token. This returns:
///
-static prec::Level getBinOpPrecedence(tok::TokenKind Kind) {
+static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
+ bool GreaterThanIsOperator) {
switch (Kind) {
+ case tok::greater:
+ // The '>' token can act as either an operator or as the ending
+ // token for a template argument list.
+ // FIXME: '>>' is similar, for error recovery and C++0x.
+ if (GreaterThanIsOperator)
+ return prec::Relational;
+ return prec::Unknown;
+
default: return prec::Unknown;
case tok::comma: return prec::Comma;
case tok::equal:
@@ -80,8 +89,7 @@
case tok::equalequal: return prec::Equality;
case tok::lessequal:
case tok::less:
- case tok::greaterequal:
- case tok::greater: return prec::Relational;
+ case tok::greaterequal: return prec::Relational;
case tok::lessless:
case tok::greatergreater: return prec::Shift;
case tok::plus:
@@ -266,7 +274,7 @@
/// LHS and has a precedence of at least MinPrec.
Parser::OwningExprResult
Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
- unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind());
+ unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
SourceLocation ColonLoc;
while (1) {
@@ -316,7 +324,7 @@
// Remember the precedence of this operator and get the precedence of the
// operator immediately to the right of the RHS.
unsigned ThisPrec = NextTokPrec;
- NextTokPrec = getBinOpPrecedence(Tok.getKind());
+ NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
// Assignment and conditional expressions are right-associative.
bool isRightAssoc = ThisPrec == prec::Conditional ||
@@ -335,7 +343,7 @@
if (RHS.isInvalid())
return move(RHS);
- NextTokPrec = getBinOpPrecedence(Tok.getKind());
+ NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
}
assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
@@ -1104,6 +1112,7 @@
Parser::ParseParenExpression(ParenParseOption &ExprType,
TypeTy *&CastTy, SourceLocation &RParenLoc) {
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
+ MakeGreaterThanAnOperator G(GreaterThanIsOperator);
SourceLocation OpenLoc = ConsumeParen();
OwningExprResult Result(Actions, true);
CastTy = 0;
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Mon Feb 9 12:46:07 2009
@@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "AstGuard.h"
using namespace clang;
@@ -354,7 +355,8 @@
/// AnnotateTemplateIdToken - The current token is an identifier that
/// refers to the template declaration Template, and is followed by a
/// '<'. Turn this template-id into a template-id annotation token.
-void Parser::AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS) {
+void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
+ const CXXScopeSpec *SS) {
assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
"Parser isn't at the beginning of a template-id");
@@ -366,13 +368,16 @@
SourceLocation LAngleLoc = ConsumeToken();
// Parse the optional template-argument-list.
- TemplateArgList TemplateArgs;
- if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) {
- // Try to find the closing '>'.
- SkipUntil(tok::greater, true, true);
-
- // FIXME: What's our recovery strategy for failed template-argument-lists?
- return;
+ ASTVector<&ActionBase::DeleteTemplateArg, 8> TemplateArgs(Actions);
+ {
+ MakeGreaterThanTemplateArgumentListTerminator G(GreaterThanIsOperator);
+ if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) {
+ // Try to find the closing '>'.
+ SkipUntil(tok::greater, true, true);
+
+ // FIXME: What's our recovery strategy for failed template-argument-lists?
+ return;
+ }
}
if (Tok.isNot(tok::greater))
@@ -382,24 +387,41 @@
// token, because we'll be replacing it with the template-id.
SourceLocation RAngleLoc = Tok.getLocation();
- Tok.setKind(tok::annot_template_id);
+ // Build the annotation token.
+ 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());
+ TemplateId->TemplateNameLoc = TemplateNameLoc;
+ TemplateId->Template = Template;
+ TemplateId->LAngleLoc = LAngleLoc;
+ TemplateId->NumArgs = TemplateArgs.size();
+ TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1);
+ for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
+ Args[Arg] = TemplateArgs[Arg];
+ Tok.setAnnotationValue(TemplateId);
+ } else {
+ // This is a type template, e.g., a class template, template
+ // template parameter, or template alias. We'll be building a
+ // "typename" annotation token.
+ TypeTy *Ty
+ = Actions.ActOnClassTemplateSpecialization(Template,LAngleLoc,
+ move_arg(TemplateArgs),
+ RAngleLoc, SS);
+ Tok.setKind(tok::annot_typename);
+ Tok.setAnnotationValue(Ty);
+ }
+
+ // Common fields for the annotation token
Tok.setAnnotationEndLoc(RAngleLoc);
Tok.setLocation(TemplateNameLoc);
if (SS && SS->isNotEmpty())
Tok.setLocation(SS->getBeginLoc());
- TemplateIdAnnotation *TemplateId
- = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
- sizeof(TemplateArgTy*) * TemplateArgs.size());
- TemplateId->TemplateNameLoc = TemplateNameLoc;
- TemplateId->Template = Template;
- TemplateId->LAngleLoc = LAngleLoc;
- TemplateId->NumArgs = TemplateArgs.size();
- TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1);
- for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
- Args[Arg] = TemplateArgs[Arg];
- Tok.setAnnotationValue(TemplateId);
-
// In case the tokens were cached, have Preprocessor replace them with the
// annotation token.
PP.AnnotateCachedTokens(Tok);
@@ -412,8 +434,22 @@
/// type-id
/// id-expression
Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
- // FIXME: Implement this!
- return TemplateArgError();
+ // 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
+ // the corresponding template-parameter.
+ //
+ // Therefore, we initially try to parse a type-id.
+ if (isTypeIdInParens()) {
+ TypeTy *TypeArg = ParseTypeName();
+ return Actions.ActOnTypeTemplateArgument(TypeArg);
+ }
+
+ OwningExprResult ExprArg = ParseExpression();
+ if (ExprArg.isInvalid())
+ return TemplateArgError();
+
+ return Actions.ActOnExprTemplateArgument(move(ExprArg));
}
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Feb 9 12:46:07 2009
@@ -20,7 +20,8 @@
using namespace clang;
Parser::Parser(Preprocessor &pp, Action &actions)
- : PP(pp), Actions(actions), Diags(PP.getDiagnostics()) {
+ : PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
+ GreaterThanIsOperator(true) {
Tok.setKind(tok::eof);
CurScope = 0;
NumCachedScopes = 0;
@@ -785,10 +786,15 @@
}
// If this is a template-id, annotate the template-id token.
- if (NextToken().is(tok::less))
- if (DeclTy *Template =
- Actions.isTemplateName(*Tok.getIdentifierInfo(), CurScope, &SS))
- AnnotateTemplateIdToken(Template, &SS);
+ if (NextToken().is(tok::less)) {
+ DeclTy *Template;
+ if (TemplateNameKind TNK
+ = Actions.isTemplateName(*Tok.getIdentifierInfo(),
+ CurScope, Template, &SS)) {
+ AnnotateTemplateIdToken(Template, TNK, &SS);
+ return true;
+ }
+ }
// We either have an identifier that is not a type name or we have
// just created a template-id that might be a type name. Both
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Feb 9 12:46:07 2009
@@ -62,6 +62,7 @@
class TypedefDecl;
class TemplateDecl;
class TemplateParameterList;
+ class TemplateArg;
class ObjCInterfaceDecl;
class ObjCCompatibleAliasDecl;
class ObjCProtocolDecl;
@@ -258,6 +259,9 @@
return OwningExprResult(*this, R.get());
}
OwningStmtResult Owned(Stmt* S) { return OwningStmtResult(*this, S); }
+ OwningTemplateArgResult Owned(TemplateArg *Arg) {
+ return OwningTemplateArgResult(*this, Arg);
+ }
virtual void ActOnEndOfTranslationUnit();
@@ -1478,8 +1482,9 @@
//===--------------------------------------------------------------------===//
// C++ Templates [C++ 14]
//
- virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS = 0);
+ virtual TemplateNameKind isTemplateName(IdentifierInfo &II, Scope *S,
+ DeclTy *&TemplateDecl,
+ const CXXScopeSpec *SS = 0);
bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(DeclTy *&Decl);
@@ -1506,6 +1511,10 @@
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,
@@ -1513,6 +1522,13 @@
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists);
+ virtual TypeTy *
+ ActOnClassTemplateSpecialization(DeclTy *Template,
+ SourceLocation LAngleLoc,
+ MultiTemplateArgsArg TemplateArgs,
+ SourceLocation RAngleLoc,
+ const CXXScopeSpec *SS = 0);
+
bool TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=64153&r1=64152&r2=64153&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Feb 9 12:46:07 2009
@@ -25,38 +25,43 @@
/// declaration if II names a template. An optional CXXScope can be
/// passed to indicate the C++ scope in which the identifier will be
/// found.
-Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS) {
- DeclContext *DC = 0;
-
- if (SS) {
- if (SS->isInvalid())
- return 0;
- DC = static_cast<DeclContext*>(SS->getScopeRep());
- }
+Sema::TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S,
+ DeclTy *&Template,
+ const CXXScopeSpec *SS) {
NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName);
if (IIDecl) {
- // FIXME: We need to represent templates via some kind of
- // TemplateDecl, because what follows is a hack that only works in
- // one specific case.
- if (isa<TemplateDecl>(IIDecl))
- return IIDecl;
+ if (isa<TemplateDecl>(IIDecl)) {
+ Template = IIDecl;
+ if (isa<FunctionTemplateDecl>(IIDecl))
+ return TNK_Function_template;
+ else if (isa<ClassTemplateDecl>(IIDecl))
+ return TNK_Class_template;
+ else if (isa<TemplateTemplateParmDecl>(IIDecl))
+ return TNK_Template_template_parm;
+ else
+ assert(false && "Unknown TemplateDecl");
+ }
+ // FIXME: What follows is a gross hack.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
- if (FD->getType()->isDependentType())
- return FD;
+ if (FD->getType()->isDependentType()) {
+ Template = FD;
+ return TNK_Function_template;
+ }
} else if (OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(IIDecl)) {
for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
FEnd = Ovl->function_end();
F != FEnd; ++F) {
- if ((*F)->getType()->isDependentType())
- return Ovl;
+ if ((*F)->getType()->isDependentType()) {
+ Template = Ovl;
+ return TNK_Function_template;
+ }
}
}
}
- return 0;
+ return TNK_Non_template;
}
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
@@ -226,6 +231,15 @@
(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,
@@ -351,6 +365,42 @@
return NewTemplate;
}
+Action::TypeTy *
+Sema::ActOnClassTemplateSpecialization(DeclTy *TemplateD,
+ SourceLocation LAngleLoc,
+ MultiTemplateArgsArg TemplateArgsIn,
+ 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();
+}
+
/// \brief Determine whether the given template parameter lists are
/// equivalent.
///
Added: cfe/trunk/test/SemaTemplate/class-template-id.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-id.cpp?rev=64153&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-id.cpp (added)
+++ cfe/trunk/test/SemaTemplate/class-template-id.cpp Mon Feb 9 12:46:07 2009
@@ -0,0 +1,17 @@
+// RUN: clang -fsyntax-only -verify %s
+template<typename T> struct A { };
+
+typedef A<int> A_int;
+
+float *foo(A<int> *ptr, A<int> const *ptr2) {
+ if (ptr)
+ return ptr; // expected-error{{incompatible type returning 'A<int> *', expected 'float *'}}
+ else if (ptr2)
+ return ptr2; // expected-error{{incompatible type returning 'A<int> const *', expected 'float *'}}
+ else {
+ // FIXME: This is completely bogus, but we're using it temporarily
+ // to test the syntactic sugar for class template specializations.
+ int *ip = ptr;
+ return 0;
+ }
+}
More information about the cfe-commits
mailing list