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
static void
packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words);
+ virtual void Destroy(ASTContext& C);
+
friend class ASTContext; // ASTContext creates these
public:
typedef void MemInitTy;
typedef void CXXScopeTy;
typedef void TemplateParamsTy;
- typedef void TemplateArgTy;
/// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
/// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and
/// Same, but with ownership.
typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult;
- typedef ASTOwningResult<&ActionBase::DeleteTemplateArg>
- OwningTemplateArgResult;
// Note that these will replace ExprResult and StmtResult when the transition
// is complete.
#if !defined(DISABLE_SMART_POINTERS)
typedef ASTOwningResult<&ActionBase::DeleteExpr> ExprArg;
typedef ASTOwningResult<&ActionBase::DeleteStmt> StmtArg;
- typedef ASTOwningResult<&ActionBase::DeleteTemplateArg> TemplateArgArg;
#else
typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg;
typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg;
- typedef ASTOwningPtr<&ActionBase::DeleteTemplateArg> TemplateArgArg;
#endif
/// Multiple expressions or statements as arguments.
typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg;
- typedef ASTMultiPtr<&ActionBase::DeleteTemplateArg> MultiTemplateArgsArg;
// Utilities for Action implementations to return smart results.
OwningExprResult ExprError() { return OwningExprResult(*this, true); }
OwningStmtResult StmtError() { return OwningStmtResult(*this, true); }
- OwningTemplateArgResult TemplateArgError() {
- return OwningTemplateArgResult(*this, true);
- }
OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
- OwningTemplateArgResult TemplateArgError(const DiagnosticBuilder&) {
- return TemplateArgError();
- }
OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); }
OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); }
- OwningTemplateArgResult TemplateArgEmpty() {
- return OwningTemplateArgResult(*this, false);
- }
/// Statistics.
virtual void PrintStats() const {}
return 0;
}
- virtual OwningTemplateArgResult ActOnTypeTemplateArgument(TypeTy *Type) {
- return TemplateArgError();
- }
-
- virtual OwningTemplateArgResult ActOnExprTemplateArgument(ExprArg Value) {
- return TemplateArgError();
- }
-
/// \brief Process the declaration or definition of a class template
/// with the given template parameter lists.
virtual DeclTy *
virtual TypeTy *
ActOnClassTemplateSpecialization(DeclTy *Template,
SourceLocation LAngleLoc,
- MultiTemplateArgsArg TemplateArgs,
+ ASTTemplateArgsPtr TemplateArgs,
SourceLocation RAngleLoc,
const CXXScopeSpec *SS = 0) {
return 0;
typedef void ExprTy;
typedef void StmtTy;
typedef void TemplateParamsTy;
- typedef void TemplateArgTy;
/// ActionResult - This structure is used while parsing/acting on
/// expressions, stmts, etc. It encapsulates both the object returned by
virtual void DeleteExpr(ExprTy *E) {}
virtual void DeleteStmt(StmtTy *E) {}
virtual void DeleteTemplateParams(TemplateParamsTy *E) {}
- virtual void DeleteTemplateArg(TemplateArgTy *E) {}
};
/// ASTDestroyer - The type of an AST node destruction function pointer.
template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
static const unsigned UID = 1;
};
- template <> struct DestroyerToUID<&ActionBase::DeleteTemplateArg> {
- static const unsigned UID = 5; // FIXME
- };
-
/// ASTOwningResult - A moveable smart pointer for AST nodes that also
/// has an extra flag to indicate an additional success status.
template <ASTDestroyer Destroyer> class ASTOwningResult;
}
#endif
};
+
+ class ASTTemplateArgsPtr {
+#if !defined(DISABLE_SMART_POINTERS)
+ ActionBase &Actions;
+#endif
+ void **Args;
+ bool *ArgIsType;
+ mutable unsigned Count;
+
+#if !defined(DISABLE_SMART_POINTERS)
+ void destroy() {
+ if (!Count)
+ return;
+
+ for (unsigned i = 0; i != Count; ++i)
+ if (Args[i] && !ArgIsType[i])
+ Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]);
+
+ Count = 0;
+ }
+#endif
+
+ public:
+ ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType,
+ unsigned count) :
+#if !defined(DISABLE_SMART_POINTERS)
+ Actions(actions),
+#endif
+ Args(args), ArgIsType(argIsType), Count(count) { }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
+#if !defined(DISABLE_SMART_POINTERS)
+ Actions(Other.Actions),
+#endif
+ Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) {
+#if !defined(DISABLE_SMART_POINTERS)
+ Other.destroy();
+#endif
+ }
+
+#if !defined(DISABLE_SMART_POINTERS)
+ ~ASTTemplateArgsPtr() { destroy(); }
+#endif
+
+ void **getArgs() const { return Args; }
+ bool *getArgIsType() const {return ArgIsType; }
+ unsigned size() const { return Count; }
+
+ void **release() const {
+#if !defined(DISABLE_SMART_POINTERS)
+ Count = 0;
+#endif
+ return Args;
+ }
+ };
#if !defined(DISABLE_SMART_POINTERS)
typedef Action::MemInitTy MemInitTy;
typedef Action::CXXScopeTy CXXScopeTy;
typedef Action::TemplateParamsTy TemplateParamsTy;
- typedef Action::TemplateArgTy TemplateArgTy;
typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists;
typedef Action::OwningExprResult OwningExprResult;
typedef Action::OwningStmtResult OwningStmtResult;
- typedef Action::OwningTemplateArgResult OwningTemplateArgResult;
typedef Action::ExprArg ExprArg;
typedef Action::MultiStmtArg MultiStmtArg;
OwningExprResult ExprError() { return OwningExprResult(Actions, true); }
OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); }
- OwningTemplateArgResult TemplateArgError() {
- return OwningTemplateArgResult(Actions, true);
- }
OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
- OwningTemplateArgResult TemplateArgError(const DiagnosticBuilder &) {
- return TemplateArgError();
- }
// Parsing methods.
DeclTy *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
DeclTy *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
// C++ 14.3: Template arguments [temp.arg]
- typedef llvm::SmallVector<TemplateArgTy*, 8> TemplateArgList;
+ typedef llvm::SmallVector<void *, 16> TemplateArgList;
+ typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList;
void AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
const CXXScopeSpec *SS = 0);
- bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
- OwningTemplateArgResult ParseTemplateArgument();
+ bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
+ TemplateArgIsTypeList &TemplateArgIsType);
+ void *ParseTemplateArgument(bool &ArgIsType);
//===--------------------------------------------------------------------===//
// GNU G++: Type Traits [Type-Traits.html in the GCC manual]
NumParams, RAngleLoc);
}
-void TemplateArg::Destroy(ASTContext &C) {
- if (Kind == ExprArg)
- getAsExpr()->Destroy(C);
-}
-
//===----------------------------------------------------------------------===//
// TemplateDecl Implementation
//===----------------------------------------------------------------------===//
Data[Arg] = Args[Arg];
}
+void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+ if (!isArgType(Arg))
+ getArgAsExpr(Arg)->Destroy(C);
+}
+
uintptr_t
ClassTemplateSpecializationType::getArgAsOpaqueValue(unsigned Arg) const {
const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
SourceLocation LAngleLoc = ConsumeToken();
// Parse the optional template-argument-list.
- ASTVector<&ActionBase::DeleteTemplateArg, 8> TemplateArgs(Actions);
+ TemplateArgList TemplateArgs;
+ TemplateArgIsTypeList TemplateArgIsType;
{
MakeGreaterThanTemplateArgumentListTerminator G(GreaterThanIsOperator);
- if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) {
+ if (Tok.isNot(tok::greater) &&
+ ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType)) {
// Try to find the closing '>'.
SkipUntil(tok::greater, true, true);
if (TNK == Action::TNK_Function_template) {
// This is a function template. We'll be building a template-id
// annotation token.
- TemplateArgs.take(); // Annotation token takes ownership
Tok.setKind(tok::annot_template_id);
TemplateIdAnnotation *TemplateId
= (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
- sizeof(TemplateArgTy*) * TemplateArgs.size());
+ sizeof(void*) * TemplateArgs.size());
TemplateId->TemplateNameLoc = TemplateNameLoc;
TemplateId->Template = Template;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->NumArgs = TemplateArgs.size();
- TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1);
+ void **Args = (void**)(TemplateId + 1);
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
Tok.setAnnotationValue(TemplateId);
// This is a type template, e.g., a class template, template
// template parameter, or template alias. We'll be building a
// "typename" annotation token.
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions, &TemplateArgs[0],
+ &TemplateArgIsType[0],
+ TemplateArgs.size());
TypeTy *Ty
- = Actions.ActOnClassTemplateSpecialization(Template,LAngleLoc,
- move_arg(TemplateArgs),
+ = Actions.ActOnClassTemplateSpecialization(Template, LAngleLoc,
+ TemplateArgsPtr,
RAngleLoc, SS);
Tok.setKind(tok::annot_typename);
Tok.setAnnotationValue(Ty);
/// assignment-expression
/// type-id
/// id-expression
-Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
+void *Parser::ParseTemplateArgument(bool &ArgIsType) {
// C++ [temp.arg]p2:
// In a template-argument, an ambiguity between a type-id and an
// expression is resolved to a type-id, regardless of the form of
//
// Therefore, we initially try to parse a type-id.
if (isTypeIdInParens()) {
- TypeTy *TypeArg = ParseTypeName();
- return Actions.ActOnTypeTemplateArgument(TypeArg);
+ ArgIsType = true;
+ return ParseTypeName();
}
OwningExprResult ExprArg = ParseExpression();
if (ExprArg.isInvalid())
- return TemplateArgError();
+ return 0;
- return Actions.ActOnExprTemplateArgument(move(ExprArg));
+ ArgIsType = false;
+ return ExprArg.release();
}
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
/// template-argument-list: [C++ 14.2]
/// template-argument
/// template-argument-list ',' template-argument
-bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
+bool
+Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
+ TemplateArgIsTypeList &TemplateArgIsType) {
while (true) {
- OwningTemplateArgResult Arg = ParseTemplateArgument();
- if (Arg.isInvalid()) {
+ bool IsType = false;
+ void *Arg = ParseTemplateArgument(IsType);
+ if (Arg) {
+ TemplateArgs.push_back(Arg);
+ TemplateArgIsType.push_back(IsType);
+ } else {
SkipUntil(tok::comma, tok::greater, true, true);
return true;
}
- else
- TemplateArgs.push_back(Arg.release());
-
+
// If the next token is a comma, consume it and keep reading
// arguments.
if (Tok.isNot(tok::comma)) break;
class TypedefDecl;
class TemplateDecl;
class TemplateParameterList;
- class TemplateArg;
class ObjCInterfaceDecl;
class ObjCCompatibleAliasDecl;
class ObjCProtocolDecl;
return OwningExprResult(*this, R.get());
}
OwningStmtResult Owned(Stmt* S) { return OwningStmtResult(*this, S); }
- OwningTemplateArgResult Owned(TemplateArg *Arg) {
- return OwningTemplateArgResult(*this, Arg);
- }
virtual void ActOnEndOfTranslationUnit();
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,
virtual TypeTy *
ActOnClassTemplateSpecialization(DeclTy *Template,
SourceLocation LAngleLoc,
- MultiTemplateArgsArg TemplateArgs,
+ ASTTemplateArgsPtr TemplateArgs,
SourceLocation RAngleLoc,
const CXXScopeSpec *SS = 0);
(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,
Action::TypeTy *
Sema::ActOnClassTemplateSpecialization(DeclTy *TemplateD,
SourceLocation LAngleLoc,
- MultiTemplateArgsArg TemplateArgsIn,
+ ASTTemplateArgsPtr TemplateArgs,
SourceLocation RAngleLoc,
const CXXScopeSpec *SS) {
TemplateDecl *Template = cast<TemplateDecl>(static_cast<Decl *>(TemplateD));
- // FIXME: Not happy about this. We should teach the parser to pass
- // us opaque pointers + bools for template argument lists.
- // FIXME: Also not happy about the fact that we leak these
- // TemplateArg structures. Fixing the above will fix this, too.
- llvm::SmallVector<uintptr_t, 16> Args;
- llvm::SmallVector<bool, 16> ArgIsType;
- unsigned NumArgs = TemplateArgsIn.size();
- TemplateArg **TemplateArgs
- = reinterpret_cast<TemplateArg **>(TemplateArgsIn.release());
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- if (Expr *ExprArg = TemplateArgs[Arg]->getAsExpr()) {
- Args.push_back(reinterpret_cast<uintptr_t>(ExprArg));
- ArgIsType.push_back(false);
- } else {
- QualType T = TemplateArgs[Arg]->getAsType();
- Args.push_back(reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()));
- ArgIsType.push_back(true);
- }
- }
-
// Yes, all class template specializations are just silly sugar for
// 'int'. Gotta problem wit dat?
- return Context.getClassTemplateSpecializationType(Template, NumArgs,
- &Args[0], &ArgIsType[0],
- Context.IntTy)
- .getAsOpaquePtr();
+ QualType Result
+ = Context.getClassTemplateSpecializationType(Template,
+ TemplateArgs.size(),
+ reinterpret_cast<uintptr_t *>(TemplateArgs.getArgs()),
+ TemplateArgs.getArgIsType(),
+ Context.IntTy);
+ TemplateArgs.release();
+ return Result.getAsOpaquePtr();
}
/// \brief Determine whether the given template parameter lists are