Index: cfe/trunk/include/clang/Parse/Parser.h =================================================================== --- cfe/trunk/include/clang/Parse/Parser.h +++ cfe/trunk/include/clang/Parse/Parser.h @@ -1017,8 +1017,8 @@ /// (C++ [class.mem]p2). struct LateParsedDefaultArgument { explicit LateParsedDefaultArgument(Decl *P, - CachedTokens *Toks = nullptr) - : Param(P), Toks(Toks) { } + std::unique_ptr Toks = nullptr) + : Param(P), Toks(std::move(Toks)) { } /// Param - The parameter declaration for this parameter. Decl *Param; @@ -1027,7 +1027,7 @@ /// argument expression, not including the '=' or the terminating /// ')' or ','. This will be NULL for parameters that have no /// default argument. - CachedTokens *Toks; + std::unique_ptr Toks; }; /// LateParsedMethodDeclaration - A method declaration inside a class that Index: cfe/trunk/include/clang/Sema/DeclSpec.h =================================================================== --- cfe/trunk/include/clang/Sema/DeclSpec.h +++ cfe/trunk/include/clang/Sema/DeclSpec.h @@ -1188,14 +1188,14 @@ /// declaration of a member function), it will be stored here as a /// sequence of tokens to be parsed once the class definition is /// complete. Non-NULL indicates that there is a default argument. - CachedTokens *DefaultArgTokens; + std::unique_ptr DefaultArgTokens; ParamInfo() = default; ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Decl *param, - CachedTokens *DefArgTokens = nullptr) + std::unique_ptr DefArgTokens = nullptr) : Ident(ident), IdentLoc(iloc), Param(param), - DefaultArgTokens(DefArgTokens) {} + DefaultArgTokens(std::move(DefArgTokens)) {} }; struct TypeAndRange { @@ -1310,10 +1310,8 @@ /// /// This is used in various places for error recovery. void freeParams() { - for (unsigned I = 0; I < NumParams; ++I) { - delete Params[I].DefaultArgTokens; - Params[I].DefaultArgTokens = nullptr; - } + for (unsigned I = 0; I < NumParams; ++I) + Params[I].DefaultArgTokens.reset(); if (DeleteParams) { delete[] Params; DeleteParams = false; Index: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp @@ -319,7 +319,8 @@ // Introduce the parameter into scope. bool HasUnparsed = Param->hasUnparsedDefaultArg(); Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param); - if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { + std::unique_ptr Toks = std::move(LM.DefaultArgs[I].Toks); + if (Toks) { // Mark the end of the default argument so that we know when to stop when // we parse it later on. Token LastDefaultArgToken = Toks->back(); @@ -377,9 +378,6 @@ if (Tok.is(tok::eof) && Tok.getEofData() == Param) ConsumeAnyToken(); - - delete Toks; - LM.DefaultArgs[I].Toks = nullptr; } else if (HasUnparsed) { assert(Param->hasInheritedDefaultArg()); FunctionDecl *Old = cast(LM.Method)->getPreviousDecl(); Index: cfe/trunk/lib/Parse/ParseDecl.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp +++ cfe/trunk/lib/Parse/ParseDecl.cpp @@ -6022,7 +6022,7 @@ // DefArgToks is used when the parsing of default arguments needs // to be delayed. - CachedTokens *DefArgToks = nullptr; + std::unique_ptr DefArgToks; // If no parameter was specified, verify that *something* was specified, // otherwise we have a missing type and identifier. @@ -6058,13 +6058,11 @@ // If we're inside a class definition, cache the tokens // corresponding to the default argument. We'll actually parse // them when we see the end of the class definition. - // FIXME: Can we use a smart pointer for Toks? - DefArgToks = new CachedTokens; + DefArgToks.reset(new CachedTokens); SourceLocation ArgStartLoc = NextToken().getLocation(); if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) { - delete DefArgToks; - DefArgToks = nullptr; + DefArgToks.reset(); Actions.ActOnParamDefaultArgumentError(Param, EqualLoc); } else { Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc, @@ -6100,7 +6098,7 @@ ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, ParmDeclarator.getIdentifierLoc(), - Param, DefArgToks)); + Param, std::move(DefArgToks))); } if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) { Index: cfe/trunk/lib/Parse/ParseDeclCXX.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp @@ -2039,7 +2039,7 @@ LateMethod->DefaultArgs.reserve(FTI.NumParams); for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument( - FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens)); + FTI.Params[ParamIdx].Param, std::move(FTI.Params[ParamIdx].DefaultArgTokens))); } } Index: cfe/trunk/lib/Sema/DeclSpec.cpp =================================================================== --- cfe/trunk/lib/Sema/DeclSpec.cpp +++ cfe/trunk/lib/Sema/DeclSpec.cpp @@ -223,13 +223,19 @@ if (!TheDeclarator.InlineStorageUsed && NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) { I.Fun.Params = TheDeclarator.InlineParams; + // Zero the memory block so that unique pointers are initialized + // properly. + memset(I.Fun.Params, 0, sizeof(Params[0]) * NumParams); I.Fun.DeleteParams = false; TheDeclarator.InlineStorageUsed = true; } else { - I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams]; + // Call the version of new that zeroes memory so that unique pointers + // are initialized properly. + I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams](); I.Fun.DeleteParams = true; } - memcpy(I.Fun.Params, Params, sizeof(Params[0]) * NumParams); + for (unsigned i = 0; i < NumParams; i++) + I.Fun.Params[i] = std::move(Params[i]); } // Check what exception specification information we should actually store. Index: cfe/trunk/lib/Sema/SemaDeclCXX.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp @@ -395,7 +395,7 @@ ++argIdx) { ParmVarDecl *Param = cast(chunk.Fun.Params[argIdx].Param); if (Param->hasUnparsedDefaultArg()) { - CachedTokens *Toks = chunk.Fun.Params[argIdx].DefaultArgTokens; + std::unique_ptr Toks = std::move(chunk.Fun.Params[argIdx].DefaultArgTokens); SourceRange SR; if (Toks->size() > 1) SR = SourceRange((*Toks)[1].getLocation(), @@ -404,8 +404,6 @@ SR = UnparsedDefaultArgLocs[Param]; Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) << SR; - delete Toks; - chunk.Fun.Params[argIdx].DefaultArgTokens = nullptr; } else if (Param->getDefaultArg()) { Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) << Param->getDefaultArg()->getSourceRange();