diff options
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 29 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 2 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 25 | ||||
-rw-r--r-- | include/clang/Parse/Ownership.h | 62 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 16 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 5 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 45 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 10 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 43 |
10 files changed, 107 insertions, 136 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index daf4210c44..b466a118b1 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -336,35 +336,6 @@ protected: 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 diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 8b9826e347..1d59489864 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1440,6 +1440,8 @@ class ClassTemplateSpecializationType static void packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words); + virtual void Destroy(ASTContext& C); + friend class ASTContext; // ASTContext creates these public: diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index b13b8ef228..14b2cea81a 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -74,7 +74,6 @@ 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 @@ -88,8 +87,6 @@ public: /// 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. @@ -97,38 +94,26 @@ public: #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 {} @@ -1126,14 +1111,6 @@ public: 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 * @@ -1158,7 +1135,7 @@ public: virtual TypeTy * ActOnClassTemplateSpecialization(DeclTy *Template, SourceLocation LAngleLoc, - MultiTemplateArgsArg TemplateArgs, + ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc, const CXXScopeSpec *SS = 0) { return 0; diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h index 6017db761f..f191d9a3b4 100644 --- a/include/clang/Parse/Ownership.h +++ b/include/clang/Parse/Ownership.h @@ -132,7 +132,6 @@ namespace clang 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 @@ -207,7 +206,6 @@ namespace clang 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. @@ -222,10 +220,6 @@ namespace clang 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; @@ -536,6 +530,62 @@ namespace clang } #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) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 7a73fcba53..a197f2c035 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -114,7 +114,6 @@ public: typedef Action::MemInitTy MemInitTy; typedef Action::CXXScopeTy CXXScopeTy; typedef Action::TemplateParamsTy TemplateParamsTy; - typedef Action::TemplateArgTy TemplateArgTy; typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists; @@ -125,7 +124,6 @@ public: typedef Action::OwningExprResult OwningExprResult; typedef Action::OwningStmtResult OwningStmtResult; - typedef Action::OwningTemplateArgResult OwningTemplateArgResult; typedef Action::ExprArg ExprArg; typedef Action::MultiStmtArg MultiStmtArg; @@ -141,15 +139,9 @@ public: 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. @@ -1029,11 +1021,13 @@ private: 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] diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index ab5a3bc0b2..4eb866d688 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -44,11 +44,6 @@ TemplateParameterList::Create(ASTContext &C, SourceLocation TemplateLoc, NumParams, RAngleLoc); } -void TemplateArg::Destroy(ASTContext &C) { - if (Kind == ExprArg) - getAsExpr()->Destroy(C); -} - //===----------------------------------------------------------------------===// // TemplateDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 6ec5062f93..bf10b9ad70 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -925,6 +925,12 @@ ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs, 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); diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 2e2cf5357f..f083be5602 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -368,10 +368,12 @@ void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK, 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); @@ -391,16 +393,15 @@ void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK, 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); @@ -408,9 +409,12 @@ void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK, // 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); @@ -433,7 +437,7 @@ void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK, /// 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 @@ -441,15 +445,16 @@ Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() { // // 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 @@ -458,16 +463,20 @@ Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() { /// 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; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index bba99fd751..ca4c528d98 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -62,7 +62,6 @@ namespace clang { class TypedefDecl; class TemplateDecl; class TemplateParameterList; - class TemplateArg; class ObjCInterfaceDecl; class ObjCCompatibleAliasDecl; class ObjCProtocolDecl; @@ -259,9 +258,6 @@ public: return OwningExprResult(*this, R.get()); } OwningStmtResult Owned(Stmt* S) { return OwningStmtResult(*this, S); } - OwningTemplateArgResult Owned(TemplateArg *Arg) { - return OwningTemplateArgResult(*this, Arg); - } virtual void ActOnEndOfTranslationUnit(); @@ -1511,10 +1507,6 @@ public: 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, @@ -1525,7 +1517,7 @@ public: virtual TypeTy * ActOnClassTemplateSpecialization(DeclTy *Template, SourceLocation LAngleLoc, - MultiTemplateArgsArg TemplateArgs, + ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc, const CXXScopeSpec *SS = 0); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 6b6a50130a..740198b11b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -231,15 +231,6 @@ Sema::ActOnTemplateParameterList(unsigned Depth, (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, @@ -368,37 +359,21 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, 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 |