2009-02-28 03:31:52 +08:00
|
|
|
//===------- 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"
|
2009-03-13 02:36:18 +08:00
|
|
|
#include "clang/AST/StmtVisitor.h"
|
2009-02-28 03:31:52 +08:00
|
|
|
#include "clang/Parse/DeclSpec.h"
|
2009-03-14 05:01:28 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h" // for the identifier table
|
2009-02-28 03:31:52 +08:00
|
|
|
#include "clang/Basic/LangOptions.h"
|
2009-02-28 08:25:32 +08:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2009-02-28 03:31:52 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2009-03-11 02:03:33 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation Support
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
|
2009-03-10 08:06:19 +08:00
|
|
|
Sema::InstantiatingTemplate::
|
|
|
|
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
ClassTemplateSpecializationDecl *Entity,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: SemaRef(SemaRef) {
|
2009-03-11 04:44:00 +08:00
|
|
|
|
|
|
|
Invalid = CheckInstantiationDepth(PointOfInstantiation,
|
|
|
|
InstantiationRange);
|
|
|
|
if (!Invalid) {
|
|
|
|
ActiveTemplateInstantiation Inst;
|
|
|
|
Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
|
|
|
|
Inst.PointOfInstantiation = PointOfInstantiation;
|
|
|
|
Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
|
2009-03-13 02:36:18 +08:00
|
|
|
Inst.TemplateArgs = 0;
|
|
|
|
Inst.NumTemplateArgs = 0;
|
2009-03-11 04:44:00 +08:00
|
|
|
Inst.InstantiationRange = InstantiationRange;
|
|
|
|
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
|
|
|
|
Invalid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
TemplateDecl *Template,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: SemaRef(SemaRef) {
|
|
|
|
|
|
|
|
Invalid = CheckInstantiationDepth(PointOfInstantiation,
|
|
|
|
InstantiationRange);
|
|
|
|
if (!Invalid) {
|
2009-03-10 08:06:19 +08:00
|
|
|
ActiveTemplateInstantiation Inst;
|
2009-03-11 04:44:00 +08:00
|
|
|
Inst.Kind
|
|
|
|
= ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
|
2009-03-10 08:06:19 +08:00
|
|
|
Inst.PointOfInstantiation = PointOfInstantiation;
|
2009-03-11 04:44:00 +08:00
|
|
|
Inst.Entity = reinterpret_cast<uintptr_t>(Template);
|
|
|
|
Inst.TemplateArgs = TemplateArgs;
|
|
|
|
Inst.NumTemplateArgs = NumTemplateArgs;
|
2009-03-10 08:06:19 +08:00
|
|
|
Inst.InstantiationRange = InstantiationRange;
|
|
|
|
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
|
|
|
|
Invalid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::InstantiatingTemplate::~InstantiatingTemplate() {
|
|
|
|
if (!Invalid)
|
|
|
|
SemaRef.ActiveTemplateInstantiations.pop_back();
|
|
|
|
}
|
|
|
|
|
2009-03-11 04:44:00 +08:00
|
|
|
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
SourceRange InstantiationRange) {
|
|
|
|
if (SemaRef.ActiveTemplateInstantiations.size()
|
|
|
|
<= SemaRef.getLangOptions().InstantiationDepth)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SemaRef.Diag(PointOfInstantiation,
|
|
|
|
diag::err_template_recursion_depth_exceeded)
|
|
|
|
<< SemaRef.getLangOptions().InstantiationDepth
|
|
|
|
<< InstantiationRange;
|
|
|
|
SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
|
|
|
|
<< SemaRef.getLangOptions().InstantiationDepth;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-03-11 02:03:33 +08:00
|
|
|
/// \brief Post-diagnostic hook for printing the instantiation stack.
|
|
|
|
void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) {
|
2009-03-11 02:52:44 +08:00
|
|
|
Sema &SemaRef = *static_cast<Sema*>(Cookie);
|
|
|
|
SemaRef.PrintInstantiationStack();
|
|
|
|
SemaRef.LastTemplateInstantiationErrorContext
|
2009-03-11 04:44:00 +08:00
|
|
|
= SemaRef.ActiveTemplateInstantiations.back();
|
2009-03-11 02:03:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Prints the current instantiation stack through a series of
|
|
|
|
/// notes.
|
|
|
|
void Sema::PrintInstantiationStack() {
|
|
|
|
for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
|
|
|
|
Active = ActiveTemplateInstantiations.rbegin(),
|
|
|
|
ActiveEnd = ActiveTemplateInstantiations.rend();
|
|
|
|
Active != ActiveEnd;
|
|
|
|
++Active) {
|
2009-03-11 04:44:00 +08:00
|
|
|
switch (Active->Kind) {
|
|
|
|
case ActiveTemplateInstantiation::TemplateInstantiation: {
|
|
|
|
ClassTemplateSpecializationDecl *Spec
|
|
|
|
= cast<ClassTemplateSpecializationDecl>((Decl*)Active->Entity);
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_template_class_instantiation_here)
|
|
|
|
<< Context.getTypeDeclType(Spec)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
|
|
|
|
TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
|
|
|
|
std::string TemplateArgsStr
|
|
|
|
= ClassTemplateSpecializationType::PrintTemplateArgumentList(
|
|
|
|
Active->TemplateArgs,
|
|
|
|
Active->NumTemplateArgs);
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_default_arg_instantiation_here)
|
|
|
|
<< (Template->getNameAsString() + TemplateArgsStr)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-03-11 02:03:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-28 03:31:52 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation for Types
|
|
|
|
//===----------------------------------------------------------------------===/
|
2009-02-28 08:25:32 +08:00
|
|
|
namespace {
|
|
|
|
class VISIBILITY_HIDDEN TemplateTypeInstantiator {
|
|
|
|
Sema &SemaRef;
|
|
|
|
const TemplateArgument *TemplateArgs;
|
|
|
|
unsigned NumTemplateArgs;
|
|
|
|
SourceLocation Loc;
|
|
|
|
DeclarationName Entity;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TemplateTypeInstantiator(Sema &SemaRef,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
|
|
|
SourceLocation Loc,
|
|
|
|
DeclarationName Entity)
|
|
|
|
: SemaRef(SemaRef), TemplateArgs(TemplateArgs),
|
|
|
|
NumTemplateArgs(NumTemplateArgs), Loc(Loc), Entity(Entity) { }
|
|
|
|
|
|
|
|
QualType operator()(QualType T) const { return Instantiate(T); }
|
|
|
|
|
|
|
|
QualType Instantiate(QualType T) const;
|
|
|
|
|
|
|
|
// Declare instantiate functions for each type.
|
|
|
|
#define TYPE(Class, Base) \
|
|
|
|
QualType Instantiate##Class##Type(const Class##Type *T, \
|
|
|
|
unsigned Quals) const;
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
};
|
|
|
|
}
|
2009-02-28 03:31:52 +08:00
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ExtQualType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 09:04:19 +08:00
|
|
|
assert(false && "Builtin types are not dependent and cannot be instantiated");
|
2009-02-28 08:25:32 +08:00
|
|
|
return QualType(T, Quals);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateFixedWidthIntType(const FixedWidthIntType *T, unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate FixedWidthIntType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ComplexType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
QualType PointeeType = Instantiate(T->getPointeeType());
|
|
|
|
if (PointeeType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.BuildPointerType(PointeeType, Quals, Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate BlockPointerType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-03-17 07:22:08 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateLValueReferenceType(
|
|
|
|
const LValueReferenceType *T, unsigned Quals) const {
|
|
|
|
QualType ReferentType = Instantiate(T->getPointeeType());
|
|
|
|
if (ReferentType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.BuildReferenceType(ReferentType, true, Quals, Loc, Entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateRValueReferenceType(
|
|
|
|
const RValueReferenceType *T, unsigned Quals) const {
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType ReferentType = Instantiate(T->getPointeeType());
|
|
|
|
if (ReferentType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
2009-03-17 07:22:08 +08:00
|
|
|
return SemaRef.BuildReferenceType(ReferentType, false, Quals, Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateMemberPointerType(const MemberPointerType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate MemberPointerType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateConstantArrayType(const ConstantArrayType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
QualType ElementType = Instantiate(T->getElementType());
|
|
|
|
if (ElementType.isNull())
|
|
|
|
return ElementType;
|
|
|
|
|
|
|
|
// Build a temporary integer literal to specify the size for
|
|
|
|
// BuildArrayType. Since we have already checked the size as part of
|
|
|
|
// creating the dependent array type in the first place, we know
|
|
|
|
// there aren't any errors.
|
2009-03-10 04:07:22 +08:00
|
|
|
// FIXME: Is IntTy big enough? Maybe not, but LongLongTy causes
|
|
|
|
// problems that I have yet to investigate.
|
|
|
|
IntegerLiteral ArraySize(T->getSize(), SemaRef.Context.IntTy, Loc);
|
2009-02-28 08:25:32 +08:00
|
|
|
return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
|
|
|
|
&ArraySize, T->getIndexTypeQualifier(),
|
|
|
|
Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateIncompleteArrayType(const IncompleteArrayType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
QualType ElementType = Instantiate(T->getElementType());
|
|
|
|
if (ElementType.isNull())
|
|
|
|
return ElementType;
|
|
|
|
|
|
|
|
return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
|
|
|
|
0, T->getIndexTypeQualifier(),
|
|
|
|
Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateVariableArrayType(const VariableArrayType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate VariableArrayType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
|
|
|
|
unsigned Quals) const {
|
2009-03-16 04:12:13 +08:00
|
|
|
Expr *ArraySize = T->getSizeExpr();
|
|
|
|
assert(ArraySize->isValueDependent() &&
|
|
|
|
"dependent sized array types must have value dependent size expr");
|
|
|
|
|
|
|
|
// Instantiate the element type if needed
|
|
|
|
QualType ElementType = T->getElementType();
|
|
|
|
if (ElementType->isDependentType()) {
|
|
|
|
ElementType = Instantiate(ElementType);
|
|
|
|
if (ElementType.isNull())
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate the size expression
|
|
|
|
Sema::OwningExprResult InstantiatedArraySize =
|
|
|
|
SemaRef.InstantiateExpr(ArraySize, TemplateArgs, NumTemplateArgs);
|
|
|
|
if (InstantiatedArraySize.isInvalid())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
|
|
|
|
(Expr *)InstantiatedArraySize.release(),
|
|
|
|
T->getIndexTypeQualifier(), Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate VectorType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateExtVectorType(const ExtVectorType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ExtVectorType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateFunctionProtoType(const FunctionProtoType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 09:04:19 +08:00
|
|
|
QualType ResultType = Instantiate(T->getResultType());
|
|
|
|
if (ResultType.isNull())
|
|
|
|
return ResultType;
|
|
|
|
|
|
|
|
llvm::SmallVector<QualType, 16> ParamTypes;
|
|
|
|
for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(),
|
|
|
|
ParamEnd = T->arg_type_end();
|
|
|
|
Param != ParamEnd; ++Param) {
|
|
|
|
QualType P = Instantiate(*Param);
|
|
|
|
if (P.isNull())
|
|
|
|
return P;
|
|
|
|
|
|
|
|
ParamTypes.push_back(P);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SemaRef.BuildFunctionType(ResultType, &ParamTypes[0],
|
|
|
|
ParamTypes.size(),
|
|
|
|
T->isVariadic(), T->getTypeQuals(),
|
|
|
|
Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateFunctionNoProtoType(const FunctionNoProtoType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 09:04:19 +08:00
|
|
|
assert(false && "Functions without prototypes cannot be dependent.");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate TypedefType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate TypeOfExprType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate TypeOfType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate RecordType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate EnumType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateTemplateTypeParmType(const TemplateTypeParmType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
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();
|
2009-02-28 08:25:32 +08:00
|
|
|
if (Result.isNull() || !Quals)
|
2009-02-28 03:31:52 +08:00
|
|
|
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.
|
2009-02-28 08:25:32 +08:00
|
|
|
if (Quals && Result->isReferenceType())
|
|
|
|
Quals = 0;
|
2009-02-28 03:31:52 +08:00
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
return QualType(Result.getTypePtr(), Quals | Result.getCVRQualifiers());
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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(),
|
2009-02-28 08:25:32 +08:00
|
|
|
T->getName())
|
|
|
|
.getQualifiedType(Quals);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateClassTemplateSpecializationType(
|
|
|
|
const ClassTemplateSpecializationType *T,
|
|
|
|
unsigned Quals) const {
|
2009-03-10 07:48:35 +08:00
|
|
|
llvm::SmallVector<TemplateArgument, 16> InstantiatedTemplateArgs;
|
|
|
|
InstantiatedTemplateArgs.reserve(T->getNumArgs());
|
|
|
|
for (ClassTemplateSpecializationType::iterator Arg = T->begin(),
|
|
|
|
ArgEnd = T->end();
|
|
|
|
Arg != ArgEnd; ++Arg) {
|
|
|
|
switch (Arg->getKind()) {
|
|
|
|
case TemplateArgument::Type: {
|
|
|
|
QualType T = SemaRef.InstantiateType(Arg->getAsType(),
|
|
|
|
TemplateArgs, NumTemplateArgs,
|
|
|
|
Arg->getLocation(),
|
|
|
|
DeclarationName());
|
|
|
|
if (T.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
InstantiatedTemplateArgs.push_back(
|
|
|
|
TemplateArgument(Arg->getLocation(), T));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateArgument::Declaration:
|
|
|
|
case TemplateArgument::Integral:
|
|
|
|
InstantiatedTemplateArgs.push_back(*Arg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TemplateArgument::Expression:
|
2009-03-14 05:01:28 +08:00
|
|
|
Sema::OwningExprResult E
|
|
|
|
= SemaRef.InstantiateExpr(Arg->getAsExpr(), TemplateArgs,
|
|
|
|
NumTemplateArgs);
|
|
|
|
if (E.isInvalid())
|
|
|
|
return QualType();
|
|
|
|
InstantiatedTemplateArgs.push_back((Expr *)E.release());
|
2009-03-10 07:48:35 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: We're missing the locations of the template name, '<', and
|
|
|
|
// '>'.
|
|
|
|
return SemaRef.CheckClassTemplateId(cast<ClassTemplateDecl>(T->getTemplate()),
|
|
|
|
Loc,
|
|
|
|
SourceLocation(),
|
|
|
|
&InstantiatedTemplateArgs[0],
|
|
|
|
InstantiatedTemplateArgs.size(),
|
|
|
|
SourceLocation());
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateQualifiedNameType(const QualifiedNameType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Cannot have dependent qualified name types (yet)");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateObjCQualifiedIdType(const ObjCQualifiedIdType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateObjCQualifiedClassType(const ObjCQualifiedClassType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
/// \brief The actual implementation of Sema::InstantiateType().
|
|
|
|
QualType TemplateTypeInstantiator::Instantiate(QualType T) const {
|
|
|
|
// 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 Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr()), \
|
|
|
|
T.getCVRQualifiers());
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(false && "Not all types have been decoded for instantiation");
|
|
|
|
return QualType();
|
|
|
|
}
|
2009-02-28 03:31:52 +08:00
|
|
|
|
|
|
|
/// \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) {
|
2009-03-11 04:44:00 +08:00
|
|
|
assert(!ActiveTemplateInstantiations.empty() &&
|
|
|
|
"Cannot perform an instantiation without some context on the "
|
|
|
|
"instantiation stack");
|
|
|
|
|
2009-02-28 03:31:52 +08:00
|
|
|
// If T is not a dependent type, there is nothing to do.
|
|
|
|
if (!T->isDependentType())
|
|
|
|
return T;
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
TemplateTypeInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs,
|
|
|
|
Loc, Entity);
|
|
|
|
return Instantiator(T);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
2009-03-03 12:44:36 +08:00
|
|
|
|
2009-03-13 00:53:44 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation for Expressions
|
|
|
|
//===----------------------------------------------------------------------===/
|
2009-03-13 02:36:18 +08:00
|
|
|
namespace {
|
|
|
|
class VISIBILITY_HIDDEN TemplateExprInstantiator
|
|
|
|
: public StmtVisitor<TemplateExprInstantiator, Sema::OwningExprResult> {
|
|
|
|
Sema &SemaRef;
|
|
|
|
const TemplateArgument *TemplateArgs;
|
|
|
|
unsigned NumTemplateArgs;
|
|
|
|
|
|
|
|
public:
|
2009-03-14 05:01:28 +08:00
|
|
|
typedef Sema::OwningExprResult OwningExprResult;
|
|
|
|
|
2009-03-13 02:36:18 +08:00
|
|
|
TemplateExprInstantiator(Sema &SemaRef,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs)
|
|
|
|
: SemaRef(SemaRef), TemplateArgs(TemplateArgs),
|
|
|
|
NumTemplateArgs(NumTemplateArgs) { }
|
|
|
|
|
|
|
|
// FIXME: Once we get closer to completion, replace these
|
|
|
|
// manually-written declarations with automatically-generated ones
|
|
|
|
// from clang/AST/StmtNodes.def.
|
2009-03-14 05:01:28 +08:00
|
|
|
OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
|
|
|
|
OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
|
|
|
|
OwningExprResult VisitParenExpr(ParenExpr *E);
|
2009-03-14 07:49:33 +08:00
|
|
|
OwningExprResult VisitUnaryOperator(UnaryOperator *E);
|
2009-03-14 05:01:28 +08:00
|
|
|
OwningExprResult VisitBinaryOperator(BinaryOperator *E);
|
|
|
|
OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
|
2009-03-18 08:55:04 +08:00
|
|
|
OwningExprResult VisitConditionalOperator(ConditionalOperator *E);
|
2009-03-14 05:01:28 +08:00
|
|
|
OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
|
|
|
|
OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
|
2009-03-17 08:28:02 +08:00
|
|
|
OwningExprResult VisitImplicitCastExpr(ImplicitCastExpr *E);
|
|
|
|
|
2009-03-13 02:36:18 +08:00
|
|
|
// Base case. I'm supposed to ignore this.
|
2009-03-16 02:34:13 +08:00
|
|
|
Sema::OwningExprResult VisitStmt(Stmt *S) {
|
|
|
|
S->dump();
|
2009-03-13 06:46:12 +08:00
|
|
|
assert(false && "Cannot instantiate this kind of expression");
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
}
|
2009-03-13 02:36:18 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitIntegerLiteral(IntegerLiteral *E) {
|
2009-03-16 02:34:13 +08:00
|
|
|
return SemaRef.Clone(E);
|
2009-03-13 02:36:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
|
|
|
|
Decl *D = E->getDecl();
|
|
|
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
|
|
|
assert(NTTP->getDepth() == 0 && "No nested templates yet");
|
2009-03-13 06:20:26 +08:00
|
|
|
const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
|
2009-03-17 07:35:25 +08:00
|
|
|
QualType T = Arg.getIntegralType();
|
|
|
|
if (T->isCharType() || T->isWideCharType())
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
|
|
|
|
Arg.getAsIntegral()->getZExtValue(),
|
|
|
|
T->isWideCharType(),
|
|
|
|
T,
|
|
|
|
E->getSourceRange().getBegin()));
|
|
|
|
else if (T->isBooleanType())
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
|
|
|
|
Arg.getAsIntegral()->getBoolValue(),
|
|
|
|
T,
|
|
|
|
E->getSourceRange().getBegin()));
|
|
|
|
|
2009-03-13 02:36:18 +08:00
|
|
|
return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
|
2009-03-13 06:20:26 +08:00
|
|
|
*Arg.getAsIntegral(),
|
2009-03-17 07:35:25 +08:00
|
|
|
T,
|
2009-03-13 06:20:26 +08:00
|
|
|
E->getSourceRange().getBegin()));
|
2009-03-13 02:36:18 +08:00
|
|
|
} else
|
|
|
|
assert(false && "Can't handle arbitrary declaration references");
|
|
|
|
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) {
|
2009-03-18 03:05:46 +08:00
|
|
|
Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
|
2009-03-13 02:36:18 +08:00
|
|
|
if (SubExpr.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) ParenExpr(
|
|
|
|
E->getLParen(), E->getRParen(),
|
|
|
|
(Expr *)SubExpr.release()));
|
|
|
|
}
|
|
|
|
|
2009-03-14 07:49:33 +08:00
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitUnaryOperator(UnaryOperator *E) {
|
|
|
|
Sema::OwningExprResult Arg = Visit(E->getSubExpr());
|
|
|
|
if (Arg.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(),
|
|
|
|
E->getOpcode(),
|
|
|
|
move(Arg));
|
|
|
|
}
|
|
|
|
|
2009-03-13 06:46:12 +08:00
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) {
|
|
|
|
Sema::OwningExprResult LHS = Visit(E->getLHS());
|
|
|
|
if (LHS.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
Sema::OwningExprResult RHS = Visit(E->getRHS());
|
|
|
|
if (RHS.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
Sema::OwningExprResult Result
|
|
|
|
= SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(),
|
|
|
|
E->getOpcode(),
|
|
|
|
(Expr *)LHS.get(),
|
|
|
|
(Expr *)RHS.get());
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
LHS.release();
|
|
|
|
RHS.release();
|
|
|
|
return move(Result);
|
|
|
|
}
|
|
|
|
|
2009-03-13 08:33:25 +08:00
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
2009-03-14 07:49:33 +08:00
|
|
|
Sema::OwningExprResult First = Visit(E->getArg(0));
|
|
|
|
if (First.isInvalid())
|
2009-03-13 08:33:25 +08:00
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
2009-03-14 07:49:33 +08:00
|
|
|
Expr *Args[2] = { (Expr *)First.get(), 0 };
|
2009-03-13 08:33:25 +08:00
|
|
|
|
2009-03-14 07:49:33 +08:00
|
|
|
Sema::OwningExprResult Second(SemaRef);
|
|
|
|
if (E->getNumArgs() == 2) {
|
|
|
|
Second = Visit(E->getArg(1));
|
|
|
|
|
|
|
|
if (Second.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
Args[1] = (Expr *)Second.get();
|
|
|
|
}
|
2009-03-14 02:40:31 +08:00
|
|
|
|
|
|
|
if (!E->isTypeDependent()) {
|
|
|
|
// Since our original expression was not type-dependent, we do not
|
|
|
|
// perform lookup again at instantiation time (C++ [temp.dep]p1).
|
|
|
|
// Instead, we just build the new overloaded operator call
|
|
|
|
// expression.
|
2009-03-14 07:49:33 +08:00
|
|
|
First.release();
|
|
|
|
Second.release();
|
2009-03-18 03:05:46 +08:00
|
|
|
// FIXME: Don't reuse the callee here. We need to instantiate it.
|
2009-03-14 02:40:31 +08:00
|
|
|
return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr(
|
|
|
|
SemaRef.Context,
|
|
|
|
E->getOperator(),
|
|
|
|
E->getCallee(),
|
2009-03-14 07:49:33 +08:00
|
|
|
Args, E->getNumArgs(),
|
|
|
|
E->getType(),
|
2009-03-14 02:40:31 +08:00
|
|
|
E->getOperatorLoc()));
|
|
|
|
}
|
|
|
|
|
2009-03-14 07:49:33 +08:00
|
|
|
bool isPostIncDec = E->getNumArgs() == 2 &&
|
|
|
|
(E->getOperator() == OO_PlusPlus || E->getOperator() == OO_MinusMinus);
|
|
|
|
if (E->getNumArgs() == 1 || isPostIncDec) {
|
|
|
|
if (!Args[0]->getType()->isOverloadableType()) {
|
|
|
|
// The argument is not of overloadable type, so try to create a
|
|
|
|
// built-in unary operation.
|
|
|
|
UnaryOperator::Opcode Opc
|
|
|
|
= UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec);
|
|
|
|
|
|
|
|
return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(), Opc,
|
|
|
|
move(First));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through to perform overload resolution
|
2009-03-14 02:40:31 +08:00
|
|
|
} else {
|
2009-03-14 07:49:33 +08:00
|
|
|
assert(E->getNumArgs() == 2 && "Expected binary operation");
|
|
|
|
|
|
|
|
Sema::OwningExprResult Result(SemaRef);
|
|
|
|
if (!Args[0]->getType()->isOverloadableType() &&
|
|
|
|
!Args[1]->getType()->isOverloadableType()) {
|
|
|
|
// Neither of the arguments is an overloadable type, so try to
|
|
|
|
// create a built-in binary operation.
|
|
|
|
BinaryOperator::Opcode Opc =
|
|
|
|
BinaryOperator::getOverloadedOpcode(E->getOperator());
|
|
|
|
Result = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), Opc,
|
|
|
|
Args[0], Args[1]);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
First.release();
|
|
|
|
Second.release();
|
|
|
|
return move(Result);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through to perform overload resolution.
|
2009-03-14 02:40:31 +08:00
|
|
|
}
|
|
|
|
|
2009-03-14 07:49:33 +08:00
|
|
|
// Compute the set of functions that were found at template
|
|
|
|
// definition time.
|
|
|
|
Sema::FunctionSet Functions;
|
|
|
|
DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee());
|
|
|
|
OverloadedFunctionDecl *Overloads
|
|
|
|
= cast<OverloadedFunctionDecl>(DRE->getDecl());
|
|
|
|
|
|
|
|
// FIXME: Do we have to check
|
|
|
|
// IsAcceptableNonMemberOperatorCandidate for each of these?
|
|
|
|
for (OverloadedFunctionDecl::function_iterator
|
|
|
|
F = Overloads->function_begin(),
|
|
|
|
FEnd = Overloads->function_end();
|
|
|
|
F != FEnd; ++F)
|
|
|
|
Functions.insert(*F);
|
|
|
|
|
|
|
|
// Add any functions found via argument-dependent lookup.
|
|
|
|
DeclarationName OpName
|
|
|
|
= SemaRef.Context.DeclarationNames.getCXXOperatorName(E->getOperator());
|
|
|
|
SemaRef.ArgumentDependentLookup(OpName, Args, E->getNumArgs(), Functions);
|
|
|
|
|
|
|
|
// Create the overloaded operator invocation.
|
|
|
|
if (E->getNumArgs() == 1 || isPostIncDec) {
|
|
|
|
UnaryOperator::Opcode Opc
|
|
|
|
= UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec);
|
|
|
|
return SemaRef.CreateOverloadedUnaryOp(E->getOperatorLoc(), Opc,
|
|
|
|
Functions, move(First));
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: This would be far less ugly if CreateOverloadedBinOp took
|
|
|
|
// in ExprArg arguments!
|
|
|
|
BinaryOperator::Opcode Opc =
|
|
|
|
BinaryOperator::getOverloadedOpcode(E->getOperator());
|
|
|
|
OwningExprResult Result
|
|
|
|
= SemaRef.CreateOverloadedBinOp(E->getOperatorLoc(), Opc,
|
|
|
|
Functions, Args[0], Args[1]);
|
|
|
|
|
2009-03-13 08:33:25 +08:00
|
|
|
if (Result.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
2009-03-14 07:49:33 +08:00
|
|
|
First.release();
|
|
|
|
Second.release();
|
2009-03-13 08:33:25 +08:00
|
|
|
return move(Result);
|
|
|
|
}
|
|
|
|
|
2009-03-18 08:55:04 +08:00
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitConditionalOperator(ConditionalOperator *E) {
|
|
|
|
Sema::OwningExprResult Cond = Visit(E->getCond());
|
|
|
|
if (Cond.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
// FIXME: use getLHS() and cope with NULLness
|
|
|
|
Sema::OwningExprResult True = Visit(E->getTrueExpr());
|
|
|
|
if (True.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
Sema::OwningExprResult False = Visit(E->getFalseExpr());
|
|
|
|
if (False.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
2009-03-19 04:12:58 +08:00
|
|
|
if (!E->isTypeDependent()) {
|
|
|
|
// Since our original expression was not type-dependent, we do not
|
|
|
|
// perform lookup again at instantiation time (C++ [temp.dep]p1).
|
|
|
|
// Instead, we just build the new conditional operator call expression.
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) ConditionalOperator(
|
2009-03-19 07:47:39 +08:00
|
|
|
Cond.takeAs<Expr>(),
|
|
|
|
True.takeAs<Expr>(),
|
|
|
|
False.takeAs<Expr>(),
|
|
|
|
E->getType()));
|
2009-03-19 04:12:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return SemaRef.ActOnConditionalOp(/*FIXME*/E->getCond()->getLocEnd(),
|
|
|
|
/*FIXME*/E->getFalseExpr()->getLocStart(),
|
2009-03-19 01:53:25 +08:00
|
|
|
move(Cond), move(True), move(False));
|
2009-03-18 08:55:04 +08:00
|
|
|
}
|
|
|
|
|
2009-03-14 05:01:28 +08:00
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
|
|
|
|
bool isSizeOf = E->isSizeOf();
|
|
|
|
|
|
|
|
if (E->isArgumentType()) {
|
|
|
|
QualType T = E->getArgumentType();
|
|
|
|
if (T->isDependentType()) {
|
|
|
|
T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
|
|
|
|
/*FIXME*/E->getOperatorLoc(),
|
2009-03-18 08:55:04 +08:00
|
|
|
&SemaRef.PP.getIdentifierTable().get("sizeof"));
|
2009-03-14 05:01:28 +08:00
|
|
|
if (T.isNull())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
return SemaRef.CreateSizeOfAlignOfExpr(T, E->getOperatorLoc(), isSizeOf,
|
|
|
|
E->getSourceRange());
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningExprResult Arg = Visit(E->getArgumentExpr());
|
|
|
|
if (Arg.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
Sema::OwningExprResult Result
|
|
|
|
= SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
|
|
|
|
isSizeOf, E->getSourceRange());
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
Arg.release();
|
|
|
|
return move(Result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateExprInstantiator::VisitCXXTemporaryObjectExpr(
|
|
|
|
CXXTemporaryObjectExpr *E) {
|
|
|
|
QualType T = E->getType();
|
|
|
|
if (T->isDependentType()) {
|
|
|
|
T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
|
|
|
|
E->getTypeBeginLoc(), DeclarationName());
|
|
|
|
if (T.isNull())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::SmallVector<Expr *, 16> Args;
|
|
|
|
Args.reserve(E->getNumArgs());
|
|
|
|
bool Invalid = false;
|
|
|
|
for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(),
|
|
|
|
ArgEnd = E->arg_end();
|
|
|
|
Arg != ArgEnd; ++Arg) {
|
|
|
|
OwningExprResult InstantiatedArg = Visit(*Arg);
|
|
|
|
if (InstantiatedArg.isInvalid()) {
|
|
|
|
Invalid = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Args.push_back((Expr *)InstantiatedArg.release());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Invalid) {
|
|
|
|
SourceLocation CommaLoc;
|
|
|
|
// FIXME: HACK!
|
|
|
|
if (Args.size() > 1)
|
|
|
|
CommaLoc
|
|
|
|
= SemaRef.PP.getLocForEndOfToken(Args[0]->getSourceRange().getEnd());
|
2009-03-16 01:47:39 +08:00
|
|
|
Sema::OwningExprResult Result(
|
|
|
|
SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()
|
|
|
|
/*, FIXME*/),
|
|
|
|
T.getAsOpaquePtr(),
|
|
|
|
/*FIXME*/E->getTypeBeginLoc(),
|
|
|
|
Sema::MultiExprArg(SemaRef,
|
|
|
|
(void**)&Args[0],
|
|
|
|
Args.size()),
|
|
|
|
/*HACK*/&CommaLoc,
|
|
|
|
E->getSourceRange().getEnd()));
|
|
|
|
// At this point, Args no longer owns the arguments, no matter what.
|
|
|
|
return move(Result);
|
2009-03-14 05:01:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up the instantiated arguments.
|
|
|
|
// FIXME: Would rather do this with RAII.
|
|
|
|
for (unsigned Idx = 0; Idx < Args.size(); ++Idx)
|
|
|
|
SemaRef.DeleteExpr(Args[Idx]);
|
|
|
|
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
}
|
|
|
|
|
2009-03-17 08:28:02 +08:00
|
|
|
Sema::OwningExprResult TemplateExprInstantiator::VisitImplicitCastExpr(
|
|
|
|
ImplicitCastExpr *E) {
|
|
|
|
assert(!E->isTypeDependent() && "Implicit casts must have known types");
|
|
|
|
|
|
|
|
Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
|
|
|
|
if (SubExpr.isInvalid())
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
ImplicitCastExpr *ICE =
|
|
|
|
new (SemaRef.Context) ImplicitCastExpr(E->getType(),
|
|
|
|
(Expr *)SubExpr.release(),
|
|
|
|
E->isLvalueCast());
|
|
|
|
return SemaRef.Owned(ICE);
|
|
|
|
}
|
|
|
|
|
2009-03-13 00:53:44 +08:00
|
|
|
Sema::OwningExprResult
|
|
|
|
Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs) {
|
2009-03-13 02:36:18 +08:00
|
|
|
TemplateExprInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs);
|
|
|
|
return Instantiator.Visit(E);
|
2009-03-13 00:53:44 +08:00
|
|
|
}
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
/// \brief Instantiate the base class specifiers of the given class
|
|
|
|
/// template specialization.
|
|
|
|
///
|
|
|
|
/// Produces a diagnostic and returns true on error, returns false and
|
|
|
|
/// attaches the instantiated base classes to the class template
|
|
|
|
/// specialization if successful.
|
|
|
|
bool
|
|
|
|
Sema::InstantiateBaseSpecifiers(
|
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
ClassTemplateDecl *ClassTemplate) {
|
|
|
|
bool Invalid = false;
|
|
|
|
llvm::SmallVector<CXXBaseSpecifier*, 8> InstantiatedBases;
|
|
|
|
for (ClassTemplateSpecializationDecl::base_class_iterator
|
|
|
|
Base = ClassTemplate->getTemplatedDecl()->bases_begin(),
|
|
|
|
BaseEnd = ClassTemplate->getTemplatedDecl()->bases_end();
|
2009-03-11 02:52:44 +08:00
|
|
|
Base != BaseEnd; ++Base) {
|
2009-03-03 12:44:36 +08:00
|
|
|
if (!Base->getType()->isDependentType()) {
|
|
|
|
// FIXME: Allocate via ASTContext
|
|
|
|
InstantiatedBases.push_back(new CXXBaseSpecifier(*Base));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType BaseType = InstantiateType(Base->getType(),
|
|
|
|
ClassTemplateSpec->getTemplateArgs(),
|
|
|
|
ClassTemplateSpec->getNumTemplateArgs(),
|
|
|
|
Base->getSourceRange().getBegin(),
|
|
|
|
DeclarationName());
|
|
|
|
if (BaseType.isNull()) {
|
|
|
|
Invalid = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CXXBaseSpecifier *InstantiatedBase
|
|
|
|
= CheckBaseSpecifier(ClassTemplateSpec,
|
|
|
|
Base->getSourceRange(),
|
|
|
|
Base->isVirtual(),
|
|
|
|
Base->getAccessSpecifierAsWritten(),
|
|
|
|
BaseType,
|
|
|
|
/*FIXME: Not totally accurate */
|
|
|
|
Base->getSourceRange().getBegin()))
|
|
|
|
InstantiatedBases.push_back(InstantiatedBase);
|
|
|
|
else
|
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
2009-03-11 02:52:44 +08:00
|
|
|
if (!Invalid &&
|
|
|
|
AttachBaseSpecifiers(ClassTemplateSpec, &InstantiatedBases[0],
|
2009-03-03 12:44:36 +08:00
|
|
|
InstantiatedBases.size()))
|
|
|
|
Invalid = true;
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Sema::InstantiateClassTemplateSpecialization(
|
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
bool ExplicitInstantiation) {
|
|
|
|
// Perform the actual instantiation on the canonical declaration.
|
|
|
|
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
|
|
|
|
Context.getCanonicalDecl(ClassTemplateSpec));
|
|
|
|
|
|
|
|
// We can only instantiate something that hasn't already been
|
|
|
|
// instantiated or specialized. Fail without any diagnostics: our
|
|
|
|
// caller will provide an error message.
|
|
|
|
if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// FIXME: Push this class template instantiation onto the
|
|
|
|
// instantiation stack, checking for recursion that exceeds a
|
|
|
|
// certain depth.
|
|
|
|
|
|
|
|
// FIXME: Perform class template partial specialization to select
|
|
|
|
// the best template.
|
|
|
|
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
|
|
|
|
|
|
|
|
if (!Template->getTemplatedDecl()->getDefinition(Context)) {
|
|
|
|
Diag(ClassTemplateSpec->getLocation(),
|
|
|
|
diag::err_template_implicit_instantiate_undefined)
|
|
|
|
<< Context.getTypeDeclType(ClassTemplateSpec);
|
|
|
|
Diag(Template->getTemplatedDecl()->getLocation(),
|
|
|
|
diag::note_template_decl_here);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note that this is an instantiation.
|
|
|
|
ClassTemplateSpec->setSpecializationKind(
|
|
|
|
ExplicitInstantiation? TSK_ExplicitInstantiation
|
|
|
|
: TSK_ImplicitInstantiation);
|
|
|
|
|
|
|
|
|
|
|
|
bool Invalid = false;
|
|
|
|
|
2009-03-10 08:06:19 +08:00
|
|
|
InstantiatingTemplate Inst(*this, ClassTemplateSpec->getLocation(),
|
|
|
|
ClassTemplateSpec);
|
|
|
|
if (Inst)
|
|
|
|
return true;
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
// Enter the scope of this instantiation. We don't use
|
|
|
|
// PushDeclContext because we don't have a scope.
|
|
|
|
DeclContext *PreviousContext = CurContext;
|
|
|
|
CurContext = ClassTemplateSpec;
|
|
|
|
|
|
|
|
// Start the definition of this instantiation.
|
|
|
|
ClassTemplateSpec->startDefinition();
|
|
|
|
|
|
|
|
// Instantiate the base class specifiers.
|
|
|
|
if (InstantiateBaseSpecifiers(ClassTemplateSpec, Template))
|
|
|
|
Invalid = true;
|
|
|
|
|
2009-03-12 00:48:53 +08:00
|
|
|
// FIXME: Create the injected-class-name for the
|
|
|
|
// instantiation. Should this be a typedef or something like it?
|
|
|
|
|
|
|
|
RecordDecl *Pattern = Template->getTemplatedDecl();
|
2009-03-12 02:59:21 +08:00
|
|
|
llvm::SmallVector<DeclTy *, 32> Fields;
|
2009-03-12 00:48:53 +08:00
|
|
|
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
|
|
|
|
MemberEnd = Pattern->decls_end();
|
|
|
|
Member != MemberEnd; ++Member) {
|
2009-03-18 05:15:40 +08:00
|
|
|
Decl *NewMember = InstantiateDecl(*Member, ClassTemplateSpec,
|
|
|
|
ClassTemplateSpec->getTemplateArgs(),
|
|
|
|
ClassTemplateSpec->getNumTemplateArgs());
|
|
|
|
if (NewMember) {
|
|
|
|
if (NewMember->isInvalidDecl())
|
2009-03-16 02:44:04 +08:00
|
|
|
Invalid = true;
|
2009-03-18 05:15:40 +08:00
|
|
|
else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
|
|
|
|
Fields.push_back(Field);
|
|
|
|
} else {
|
|
|
|
// FIXME: Eventually, a NULL return will mean that one of the
|
|
|
|
// instantiations was a semantic disaster, and we'll want to set
|
|
|
|
// Invalid = true. For now, we expect to skip some members that
|
|
|
|
// we can't yet handle.
|
2009-03-12 00:48:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-12 02:59:21 +08:00
|
|
|
// Finish checking fields.
|
|
|
|
ActOnFields(0, ClassTemplateSpec->getLocation(), ClassTemplateSpec,
|
|
|
|
&Fields[0], Fields.size(), SourceLocation(), SourceLocation(),
|
|
|
|
0);
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
// Add any implicitly-declared members that we might need.
|
|
|
|
AddImplicitlyDeclaredMembersToClass(ClassTemplateSpec);
|
|
|
|
|
|
|
|
// Exit the scope of this instantiation.
|
|
|
|
CurContext = PreviousContext;
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
}
|