diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 34 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 32 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 5 |
7 files changed, 71 insertions, 14 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5077c35acb6..e81444ebe73 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2354,7 +2354,8 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'. QualType Ty = FPT->getArgType(1); ASTContext &Ctx = getASTContext(); - if (Ctx.getLangOpts().SizedDeallocation && Ty == Ctx.getSizeType()) + if (Ctx.getLangOpts().SizedDeallocation && + Ctx.hasSameType(Ty, Ctx.getSizeType())) return true; if (!Ty->isReferenceType()) return false; @@ -2366,6 +2367,37 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { return RD && isNamed(RD, "nothrow_t") && isNamespaceStd(RD->getDeclContext()); } +FunctionDecl * +FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const { + ASTContext &Ctx = getASTContext(); + if (!Ctx.getLangOpts().SizedDeallocation) + return 0; + + if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) + return 0; + if (getDeclName().getCXXOverloadedOperator() != OO_Delete && + getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) + return 0; + if (isa<CXXRecordDecl>(getDeclContext())) + return 0; + assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + + if (getNumParams() != 2 || isVariadic() || + !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getArgType(1), + Ctx.getSizeType())) + return 0; + + // This is a sized deallocation function. Find the corresponding unsized + // deallocation function. + lookup_const_result R = getDeclContext()->lookup(getDeclName()); + for (lookup_const_result::iterator RI = R.begin(), RE = R.end(); RI != RE; + ++RI) + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI)) + if (FD->getNumParams() == 1 && !FD->isVariadic()) + return FD; + return 0; +} + LanguageLinkage FunctionDecl::getLanguageLinkage() const { return getLanguageLinkageTemplate(*this); } diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index af8cbbc48c2..4848d7565d4 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2180,7 +2180,7 @@ void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) { return; } - EmitFunctionBody(Args); + EmitFunctionBody(Args, cast<FunctionDecl>(CurGD.getDecl())->getBody()); } void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 221d132ee0b..4a427d540f6 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1824,8 +1824,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { return LV; } - if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND)) - return EmitFunctionDeclLValue(*this, E, fn); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) + return EmitFunctionDeclLValue(*this, E, FD); llvm_unreachable("Unhandled DeclRefExpr"); } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 3ec890383c9..ce1b44559dc 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -643,13 +643,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, DI->EmitLocation(Builder, StartLoc); } -void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args) { - const FunctionDecl *FD = cast<FunctionDecl>(CurGD.getDecl()); - assert(FD->getBody()); - if (const CompoundStmt *S = dyn_cast<CompoundStmt>(FD->getBody())) +void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args, + const Stmt *Body) { + if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body)) EmitCompoundStmtWithoutScope(*S); else - EmitStmt(FD->getBody()); + EmitStmt(Body); } /// Tries to mark the given function nounwind based on the @@ -672,6 +671,17 @@ static void TryMarkNoThrow(llvm::Function *F) { F->setDoesNotThrow(); } +static void EmitSizedDeallocationFunction(CodeGenFunction &CGF, + const FunctionDecl *UnsizedDealloc) { + // This is a weak discardable definition of the sized deallocation function. + CGF.CurFn->setLinkage(llvm::Function::LinkOnceAnyLinkage); + + // Call the unsized deallocation function and forward the first argument + // unchanged. + llvm::Constant *Unsized = CGF.CGM.GetAddrOfFunction(UnsizedDealloc); + CGF.Builder.CreateCall(Unsized, &*CGF.CurFn->arg_begin()); +} + void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); @@ -726,9 +736,15 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, // Implicit copy-assignment gets the same special treatment as implicit // copy-constructors. emitImplicitAssignmentOperatorBody(Args); - } - else - EmitFunctionBody(Args); + } else if (Stmt *Body = FD->getBody()) { + EmitFunctionBody(Args, Body); + } else if (FunctionDecl *UnsizedDealloc = + FD->getCorrespondingUnsizedGlobalDeallocationFunction()) { + // Global sized deallocation functions get an implicit weak definition if + // they don't have an explicit definition. + EmitSizedDeallocationFunction(*this, UnsizedDealloc); + } else + llvm_unreachable("no definition for emitted function"); // C++11 [stmt.return]p2: // Flowing off the end of a function [...] results in undefined behavior in diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index b07e903b49f..98c090fa149 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1136,7 +1136,7 @@ public: void EmitConstructorBody(FunctionArgList &Args); void EmitDestructorBody(FunctionArgList &Args); void emitImplicitAssignmentOperatorBody(FunctionArgList &Args); - void EmitFunctionBody(FunctionArgList &Args); + void EmitFunctionBody(FunctionArgList &Args, const Stmt *Body); void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator, CallArgList &CallArgs); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d0f34dddca3..c34f8332699 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1406,6 +1406,12 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, DeferredDeclsToEmit.push_back(DDI->second); DeferredDecls.erase(DDI); + // Otherwise, if this is a sized deallocation function, emit a weak definition + // for it at the end of the translation unit. + } else if (D && cast<FunctionDecl>(D) + ->getCorrespondingUnsizedGlobalDeallocationFunction()) { + DeferredDeclsToEmit.push_back(GD); + // Otherwise, there are cases we have to worry about where we're // using a declaration for which we must emit a definition but where // we might not find a top-level definition: diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 3da8ba7309a..a523acfc431 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1093,6 +1093,9 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.Trigraphs = !Opts.GNUMode; Opts.DollarIdents = !Opts.AsmPreprocessor; + + // C++1y onwards has sized global deallocation functions. + Opts.SizedDeallocation = Opts.CPlusPlus1y; } /// Attempt to parse a visibility value out of the given argument. @@ -1310,7 +1313,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); - Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation); + Opts.SizedDeallocation |= Args.hasArg(OPT_fsized_deallocation); Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); Opts.AccessControl = !Args.hasArg(OPT_fno_access_control); Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); |