Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -497,6 +497,7 @@ def CharSubscript : DiagGroup<"char-subscripts">; def LargeByValueCopy : DiagGroup<"large-by-value-copy">; def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">; +def DuplicateMangledNames : DiagGroup<"duplicate-mangled-names">; // Unreachable code warning groups. // Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2316,8 +2316,9 @@ def warn_alias_with_section : Warning< "alias will not be in section '%0' but in the same section as the aliasee">, InGroup; -def err_duplicate_mangled_name : Error< - "definition with same mangled name as another definition">; +def warn_duplicate_mangled_name : Warning< + "definition with same mangled name as another definition">, + InGroup; def err_cyclic_alias : Error< "alias definition is part of a cycle">; def warn_attribute_wrong_decl_type : Warning< Index: lib/CodeGen/CGCXX.cpp =================================================================== --- lib/CodeGen/CGCXX.cpp +++ lib/CodeGen/CGCXX.cpp @@ -207,7 +207,8 @@ const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(MD, Type); auto *Fn = cast( - getAddrOfCXXStructor(MD, Type, &FnInfo, nullptr, true)); + getAddrOfCXXStructor(MD, Type, &FnInfo, /*FnType=*/nullptr, + /*DontDefer=*/true, /*IsForDefinition=*/true)); GlobalDecl GD; if (const auto *DD = dyn_cast(MD)) { @@ -226,9 +227,9 @@ return Fn; } -llvm::GlobalValue *CodeGenModule::getAddrOfCXXStructor( +llvm::Constant *CodeGenModule::getAddrOfCXXStructor( const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo, - llvm::FunctionType *FnType, bool DontDefer) { + llvm::FunctionType *FnType, bool DontDefer, bool IsForDefinition) { GlobalDecl GD; if (auto *CD = dyn_cast(MD)) { GD = GlobalDecl(CD, toCXXCtorType(Type)); @@ -236,19 +237,15 @@ GD = GlobalDecl(cast(MD), toCXXDtorType(Type)); } - StringRef Name = getMangledName(GD); - if (llvm::GlobalValue *Existing = GetGlobalValue(Name)) - return Existing; - if (!FnType) { if (!FnInfo) FnInfo = &getTypes().arrangeCXXStructorDeclaration(MD, Type); FnType = getTypes().GetFunctionType(*FnInfo); } - return cast(GetOrCreateLLVMFunction(Name, FnType, GD, - /*ForVTable=*/false, - DontDefer)); + return GetOrCreateLLVMFunction( + getMangledName(GD), FnType, GD, /*ForVTable=*/false, DontDefer, + /*isThunk=*/false, /*ExtraAttrs=*/llvm::AttributeSet(), IsForDefinition); } static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF, Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -342,6 +342,17 @@ typedef llvm::StringMap > ReplacementsTy; ReplacementsTy Replacements; + /// List of global values to be replaced with something else Used when we want + /// to replace a GlobalValue but can't identify it by its mangled name anymore + /// (because the name is already taken). + llvm::SmallVector, 8> + GlobalValReplacements; + + /// Set of global decls for which definitions are explicitly requested to be + /// created (by passing IsForDefinition as true in GetOrCreateLLVMFunction + /// call). + llvm::DenseSet ExplicitDefinitions; + /// A queue of (optional) vtables to consider emitting. std::vector DeferredVTables; @@ -682,18 +693,7 @@ llvm_unreachable("unknown visibility!"); } - llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) { - if (isa(GD.getDecl())) - return getAddrOfCXXStructor(cast(GD.getDecl()), - getFromCtorType(GD.getCtorType())); - else if (isa(GD.getDecl())) - return getAddrOfCXXStructor(cast(GD.getDecl()), - getFromDtorType(GD.getDtorType())); - else if (isa(GD.getDecl())) - return GetAddrOfFunction(GD); - else - return GetAddrOfGlobalVar(cast(GD.getDecl())); - } + llvm::Constant *GetAddrOfGlobal(GlobalDecl GD, bool IsForDefinition = false); /// Will return a global variable of the given type. If a variable with a /// different type already exists then a new variable with the right type @@ -725,7 +725,8 @@ /// function will use the specified type if it has to create it. llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = 0, bool ForVTable = false, - bool DontDefer = false); + bool DontDefer = false, + bool IsForDefinition = false); /// Get the address of the RTTI descriptor for the given type. llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false); @@ -847,11 +848,11 @@ StructorType Type); /// Return the address of the constructor/destructor of the given type. - llvm::GlobalValue * + llvm::Constant * getAddrOfCXXStructor(const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo = nullptr, llvm::FunctionType *FnType = nullptr, - bool DontDefer = false); + bool DontDefer = false, bool IsForDefinition = false); /// Given a builtin id for a function like "__builtin_fabsf", return a /// Function* for "fabsf". @@ -1122,6 +1123,8 @@ void addReplacement(StringRef Name, llvm::Constant *C); + void addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C); + /// \brief Emit a code for threadprivate directive. /// \param D Threadprivate declaration. void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D); @@ -1148,7 +1151,8 @@ GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable, bool DontDefer = false, bool IsThunk = false, - llvm::AttributeSet ExtraAttrs = llvm::AttributeSet()); + llvm::AttributeSet ExtraAttrs = llvm::AttributeSet(), + bool IsForDefinition = false); llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName, llvm::PointerType *PTy, @@ -1211,6 +1215,9 @@ /// Call replaceAllUsesWith on all pairs in Replacements. void applyReplacements(); + /// Call replaceAllUsesWith on all pairs in GlobalValReplacements. + void applyGlobalValReplacements(); + void checkAliases(); /// Emit any vtables which we deferred and still have a use for. Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -237,6 +237,20 @@ } } +void CodeGenModule::addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C) { + GlobalValReplacements.push_back(std::make_pair(GV, C)); +} + +void CodeGenModule::applyGlobalValReplacements() { + for (auto &I : GlobalValReplacements) { + llvm::GlobalValue *GV = I.first; + llvm::Constant *C = I.second; + + GV->replaceAllUsesWith(C); + GV->eraseFromParent(); + } +} + // This is only used in aliases that we created and we know they have a // linear structure. static const llvm::GlobalObject *getAliasedGlobal(const llvm::GlobalAlias &GA) { @@ -339,6 +353,7 @@ void CodeGenModule::Release() { EmitDeferred(); + applyGlobalValReplacements(); applyReplacements(); checkAliases(); EmitCXXGlobalInitFunc(); @@ -1108,8 +1123,19 @@ llvm::GlobalValue *GV = G.GV; G.GV = nullptr; - assert(!GV || GV == GetGlobalValue(getMangledName(D))); - if (!GV) + // Name of this global value is taken => it will be replaced, so no need to + // emit it. + if (GV && GV != GetGlobalValue(getMangledName(D))) + continue; + + // We should call GetAddrOfGlobal with IsForDefinition set to true in order + // to get GlobalValue with exactly the type we need, not something that + // might had been created for another decl with the same mangled name but + // different type. + // FIXME: Support for variables is not implemented yet. + if (isa(D.getDecl())) + GV = cast(GetAddrOfGlobal(D, /*IsForDefinition=*/true)); + else GV = GetGlobalValue(getMangledName(D)); // Check to see if we've already emitted this. This is necessary @@ -1541,6 +1567,140 @@ llvm_unreachable("Invalid argument to EmitGlobalDefinition()"); } +/// Replace the uses of a function that was declared with a non-proto type. +/// We want to silently drop extra arguments from call sites +static void replaceUsesOfNonProtoConstant(llvm::Constant *old, + llvm::Function *newFn) { + // Fast path. + if (old->use_empty()) return; + + llvm::Type *newRetTy = newFn->getReturnType(); + SmallVector newArgs; + + for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end(); + ui != ue; ) { + llvm::Value::use_iterator use = ui++; // Increment before the use is erased. + llvm::User *user = use->getUser(); + + // Recognize and replace uses of bitcasts. Most calls to + // unprototyped functions will use bitcasts. + if (auto *bitcast = dyn_cast(user)) { + if (bitcast->getOpcode() == llvm::Instruction::BitCast) + replaceUsesOfNonProtoConstant(bitcast, newFn); + continue; + } + + // Recognize calls to the function. + llvm::CallSite callSite(user); + if (!callSite) continue; + if (!callSite.isCallee(&*use)) continue; + + // If the return types don't match exactly, then we can't + // transform this call unless it's dead. + if (callSite->getType() != newRetTy && !callSite->use_empty()) + continue; + + // Get the call site's attribute list. + SmallVector newAttrs; + llvm::AttributeSet oldAttrs = callSite.getAttributes(); + + // Collect any return attributes from the call. + if (oldAttrs.hasAttributes(llvm::AttributeSet::ReturnIndex)) + newAttrs.push_back( + llvm::AttributeSet::get(newFn->getContext(), + oldAttrs.getRetAttributes())); + + // If the function was passed too few arguments, don't transform. + unsigned newNumArgs = newFn->arg_size(); + if (callSite.arg_size() < newNumArgs) continue; + + // If extra arguments were passed, we silently drop them. + // If any of the types mismatch, we don't transform. + unsigned argNo = 0; + bool dontTransform = false; + for (llvm::Function::arg_iterator ai = newFn->arg_begin(), + ae = newFn->arg_end(); ai != ae; ++ai, ++argNo) { + if (callSite.getArgument(argNo)->getType() != ai->getType()) { + dontTransform = true; + break; + } + + // Add any parameter attributes. + if (oldAttrs.hasAttributes(argNo + 1)) + newAttrs. + push_back(llvm:: + AttributeSet::get(newFn->getContext(), + oldAttrs.getParamAttributes(argNo + 1))); + } + if (dontTransform) + continue; + + if (oldAttrs.hasAttributes(llvm::AttributeSet::FunctionIndex)) + newAttrs.push_back(llvm::AttributeSet::get(newFn->getContext(), + oldAttrs.getFnAttributes())); + + // Okay, we can transform this. Create the new call instruction and copy + // over the required information. + newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo); + + llvm::CallSite newCall; + if (callSite.isCall()) { + newCall = llvm::CallInst::Create(newFn, newArgs, "", + callSite.getInstruction()); + } else { + auto *oldInvoke = cast(callSite.getInstruction()); + newCall = llvm::InvokeInst::Create(newFn, + oldInvoke->getNormalDest(), + oldInvoke->getUnwindDest(), + newArgs, "", + callSite.getInstruction()); + } + newArgs.clear(); // for the next iteration + + if (!newCall->getType()->isVoidTy()) + newCall->takeName(callSite.getInstruction()); + newCall.setAttributes( + llvm::AttributeSet::get(newFn->getContext(), newAttrs)); + newCall.setCallingConv(callSite.getCallingConv()); + + // Finally, remove the old call, replacing any uses with the new one. + if (!callSite->use_empty()) + callSite->replaceAllUsesWith(newCall.getInstruction()); + + // Copy debug location attached to CI. + if (callSite->getDebugLoc()) + newCall->setDebugLoc(callSite->getDebugLoc()); + callSite->eraseFromParent(); + } +} + +/// ReplaceUsesOfNonProtoTypeWithRealFunction - This function is called when we +/// implement a function with no prototype, e.g. "int foo() {}". If there are +/// existing call uses of the old function in the module, this adjusts them to +/// call the new function directly. +/// +/// This is not just a cleanup: the always_inline pass requires direct calls to +/// functions to be able to inline them. If there is a bitcast in the way, it +/// won't inline them. Instcombine normally deletes these calls, but it isn't +/// run at -O0. +static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, + llvm::Function *NewFn) { + // If we're redefining a global as a function, don't transform it. + if (!isa(Old)) return; + + replaceUsesOfNonProtoConstant(Old, NewFn); +} + +void CodeGenModule::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) { + TemplateSpecializationKind TSK = VD->getTemplateSpecializationKind(); + // If we have a definition, this might be a deferred decl. If the + // instantiation is explicit, make sure we emit it at the end. + if (VD->getDefinition() && TSK == TSK_ExplicitInstantiationDefinition) + GetAddrOfGlobalVar(VD); + + EmitTopLevelDecl(VD); +} + /// GetOrCreateLLVMFunction - If the specified mangled name is not in the /// module, create and return an llvm Function with the specified type. If there /// is something in the module with the specified name, return it potentially @@ -1553,7 +1713,8 @@ llvm::Type *Ty, GlobalDecl GD, bool ForVTable, bool DontDefer, bool IsThunk, - llvm::AttributeSet ExtraAttrs) { + llvm::AttributeSet ExtraAttrs, + bool IsForDefinition) { const Decl *D = GD.getDecl(); // Lookup the entry, lazily creating it if necessary. @@ -1569,11 +1730,32 @@ if (D && !D->hasAttr() && !D->hasAttr()) Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - if (Entry->getType()->getElementType() == Ty) + // If there are two attempts to define the same mangled name, issue a + // warning. + // + // Check that GD is not yet in ExplicitDefinitions is required to make sure + // that we issue a warning only once. + if (IsForDefinition && + (ExplicitDefinitions.find(GD) == ExplicitDefinitions.end())) { + GlobalDecl OtherGD; + if (lookupRepresentativeDecl(MangledName, OtherGD) && + (ExplicitDefinitions.find(OtherGD) != ExplicitDefinitions.end())) { + getDiags().Report(D->getLocation(), + diag::warn_duplicate_mangled_name); + getDiags().Report(OtherGD.getDecl()->getLocation(), + diag::note_previous_definition); + } + } + + if ((isa(Entry) || isa(Entry)) && + (Entry->getType()->getElementType() == Ty)) return Entry; // Make sure the result is of the correct type. - return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo()); + // (If function is requested for a definition, we always need to create a new + // function, not just return a bitcast.) + if (!IsForDefinition) + return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo()); } // This function doesn't have a complete type (for example, the return @@ -1588,10 +1770,41 @@ FTy = llvm::FunctionType::get(VoidTy, false); IsIncompleteFunction = true; } - - llvm::Function *F = llvm::Function::Create(FTy, - llvm::Function::ExternalLinkage, - MangledName, &getModule()); + + llvm::Function *F = + llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, + Entry ? StringRef() : MangledName, &getModule()); + + // If we already created a function with the same mangled name (but different + // type) before, take its name and add it to the list of functions to be + // replaced with F at the end of CodeGen. + // + // This happens if there is a prototype for a function (e.g. "int f()") and + // then a definition of a different type (e.g. "int f(int x)"). + if (Entry) { + F->takeName(Entry); + + // This might be an implementation of a function without a prototype, in + // which case, try to do special replacement of calls which match the new + // prototype. The really key thing here is that we also potentially drop + // arguments from the call site so as to make a direct call, which makes the + // inliner happier and suppresses a number of optimizer warnings (!) about + // dropping arguments. + if (!Entry->use_empty()) { + ReplaceUsesOfNonProtoTypeWithRealFunction(Entry, F); + Entry->removeDeadConstantUsers(); + } + + llvm::Constant *BC = llvm::ConstantExpr::getBitCast( + F, Entry->getType()->getElementType()->getPointerTo()); + addGlobalValReplacement(Entry, BC); + } + + // If we are explicitly requested to create a function for a definition, + // remember this. + if (IsForDefinition) + ExplicitDefinitions.insert(GD); + assert(F->getName() == MangledName && "name was uniqued!"); if (D) SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk); @@ -1664,13 +1877,16 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty, bool ForVTable, - bool DontDefer) { + bool DontDefer, + bool IsForDefinition) { // If there was no specific requested type, just convert it now. if (!Ty) Ty = getTypes().ConvertType(cast(GD.getDecl())->getType()); - + StringRef MangledName = getMangledName(GD); - return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer); + return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer, + /*IsThunk=*/false, llvm::AttributeSet(), + IsForDefinition); } /// CreateRuntimeFunction - Create a new runtime function with the specified @@ -1809,6 +2025,33 @@ return GV; } +llvm::Constant * +CodeGenModule::GetAddrOfGlobal(GlobalDecl GD, + bool IsForDefinition) { + if (isa(GD.getDecl())) + return getAddrOfCXXStructor(cast(GD.getDecl()), + getFromCtorType(GD.getCtorType()), + /*FnInfo=*/nullptr, /*FnType=*/nullptr, + /*DontDefer=*/false, IsForDefinition); + else if (isa(GD.getDecl())) + return getAddrOfCXXStructor(cast(GD.getDecl()), + getFromDtorType(GD.getDtorType()), + /*FnInfo=*/nullptr, /*FnType=*/nullptr, + /*DontDefer=*/false, IsForDefinition); + else if (isa(GD.getDecl())) { + auto FInfo = &getTypes().arrangeCXXMethodDeclaration( + cast(GD.getDecl())); + auto Ty = getTypes().GetFunctionType(*FInfo); + return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false, + IsForDefinition); + } else if (isa(GD.getDecl())) { + const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); + llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); + return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false, + IsForDefinition); + } else + return GetAddrOfGlobalVar(cast(GD.getDecl())); +} llvm::GlobalVariable * CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name, @@ -2258,140 +2501,6 @@ return getLLVMLinkageForDeclarator(VD, Linkage, IsConstant); } -/// Replace the uses of a function that was declared with a non-proto type. -/// We want to silently drop extra arguments from call sites -static void replaceUsesOfNonProtoConstant(llvm::Constant *old, - llvm::Function *newFn) { - // Fast path. - if (old->use_empty()) return; - - llvm::Type *newRetTy = newFn->getReturnType(); - SmallVector newArgs; - - for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end(); - ui != ue; ) { - llvm::Value::use_iterator use = ui++; // Increment before the use is erased. - llvm::User *user = use->getUser(); - - // Recognize and replace uses of bitcasts. Most calls to - // unprototyped functions will use bitcasts. - if (auto *bitcast = dyn_cast(user)) { - if (bitcast->getOpcode() == llvm::Instruction::BitCast) - replaceUsesOfNonProtoConstant(bitcast, newFn); - continue; - } - - // Recognize calls to the function. - llvm::CallSite callSite(user); - if (!callSite) continue; - if (!callSite.isCallee(&*use)) continue; - - // If the return types don't match exactly, then we can't - // transform this call unless it's dead. - if (callSite->getType() != newRetTy && !callSite->use_empty()) - continue; - - // Get the call site's attribute list. - SmallVector newAttrs; - llvm::AttributeSet oldAttrs = callSite.getAttributes(); - - // Collect any return attributes from the call. - if (oldAttrs.hasAttributes(llvm::AttributeSet::ReturnIndex)) - newAttrs.push_back( - llvm::AttributeSet::get(newFn->getContext(), - oldAttrs.getRetAttributes())); - - // If the function was passed too few arguments, don't transform. - unsigned newNumArgs = newFn->arg_size(); - if (callSite.arg_size() < newNumArgs) continue; - - // If extra arguments were passed, we silently drop them. - // If any of the types mismatch, we don't transform. - unsigned argNo = 0; - bool dontTransform = false; - for (llvm::Function::arg_iterator ai = newFn->arg_begin(), - ae = newFn->arg_end(); ai != ae; ++ai, ++argNo) { - if (callSite.getArgument(argNo)->getType() != ai->getType()) { - dontTransform = true; - break; - } - - // Add any parameter attributes. - if (oldAttrs.hasAttributes(argNo + 1)) - newAttrs. - push_back(llvm:: - AttributeSet::get(newFn->getContext(), - oldAttrs.getParamAttributes(argNo + 1))); - } - if (dontTransform) - continue; - - if (oldAttrs.hasAttributes(llvm::AttributeSet::FunctionIndex)) - newAttrs.push_back(llvm::AttributeSet::get(newFn->getContext(), - oldAttrs.getFnAttributes())); - - // Okay, we can transform this. Create the new call instruction and copy - // over the required information. - newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo); - - llvm::CallSite newCall; - if (callSite.isCall()) { - newCall = llvm::CallInst::Create(newFn, newArgs, "", - callSite.getInstruction()); - } else { - auto *oldInvoke = cast(callSite.getInstruction()); - newCall = llvm::InvokeInst::Create(newFn, - oldInvoke->getNormalDest(), - oldInvoke->getUnwindDest(), - newArgs, "", - callSite.getInstruction()); - } - newArgs.clear(); // for the next iteration - - if (!newCall->getType()->isVoidTy()) - newCall->takeName(callSite.getInstruction()); - newCall.setAttributes( - llvm::AttributeSet::get(newFn->getContext(), newAttrs)); - newCall.setCallingConv(callSite.getCallingConv()); - - // Finally, remove the old call, replacing any uses with the new one. - if (!callSite->use_empty()) - callSite->replaceAllUsesWith(newCall.getInstruction()); - - // Copy debug location attached to CI. - if (callSite->getDebugLoc()) - newCall->setDebugLoc(callSite->getDebugLoc()); - callSite->eraseFromParent(); - } -} - -/// ReplaceUsesOfNonProtoTypeWithRealFunction - This function is called when we -/// implement a function with no prototype, e.g. "int foo() {}". If there are -/// existing call uses of the old function in the module, this adjusts them to -/// call the new function directly. -/// -/// This is not just a cleanup: the always_inline pass requires direct calls to -/// functions to be able to inline them. If there is a bitcast in the way, it -/// won't inline them. Instcombine normally deletes these calls, but it isn't -/// run at -O0. -static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, - llvm::Function *NewFn) { - // If we're redefining a global as a function, don't transform it. - if (!isa(Old)) return; - - replaceUsesOfNonProtoConstant(Old, NewFn); -} - -void CodeGenModule::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) { - TemplateSpecializationKind TSK = VD->getTemplateSpecializationKind(); - // If we have a definition, this might be a deferred decl. If the - // instantiation is explicit, make sure we emit it at the end. - if (VD->getDefinition() && TSK == TSK_ExplicitInstantiationDefinition) - GetAddrOfGlobalVar(VD); - - EmitTopLevelDecl(VD); -} - void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { const auto *D = cast(GD.getDecl()); @@ -2401,66 +2510,14 @@ llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); // Get or create the prototype for the function. - if (!GV) { - llvm::Constant *C = - GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true); - - // Strip off a bitcast if we got one back. - if (auto *CE = dyn_cast(C)) { - assert(CE->getOpcode() == llvm::Instruction::BitCast); - GV = cast(CE->getOperand(0)); - } else { - GV = cast(C); - } - } + if (!GV || (GV->getType()->getElementType() != Ty)) + GV = cast(GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, + /*DontDefer=*/true, + /*IsForDefinition=*/true)); - if (!GV->isDeclaration()) { - getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name); - GlobalDecl OldGD = Manglings.lookup(GV->getName()); - if (auto *Prev = OldGD.getDecl()) - getDiags().Report(Prev->getLocation(), diag::note_previous_definition); + // Already emitted. + if (!GV->isDeclaration()) return; - } - - if (GV->getType()->getElementType() != Ty) { - // If the types mismatch then we have to rewrite the definition. - assert(GV->isDeclaration() && "Shouldn't replace non-declaration"); - - // F is the Function* for the one with the wrong type, we must make a new - // Function* and update everything that used F (a declaration) with the new - // Function* (which will be a definition). - // - // This happens if there is a prototype for a function - // (e.g. "int f()") and then a definition of a different type - // (e.g. "int f(int x)"). Move the old function aside so that it - // doesn't interfere with GetAddrOfFunction. - GV->setName(StringRef()); - auto *NewFn = cast(GetAddrOfFunction(GD, Ty)); - - // This might be an implementation of a function without a - // prototype, in which case, try to do special replacement of - // calls which match the new prototype. The really key thing here - // is that we also potentially drop arguments from the call site - // so as to make a direct call, which makes the inliner happier - // and suppresses a number of optimizer warnings (!) about - // dropping arguments. - if (!GV->use_empty()) { - ReplaceUsesOfNonProtoTypeWithRealFunction(GV, NewFn); - GV->removeDeadConstantUsers(); - } - - // Replace uses of F with the Function we will endow with a body. - if (!GV->use_empty()) { - llvm::Constant *NewPtrForOldDecl = - llvm::ConstantExpr::getBitCast(NewFn, GV->getType()); - GV->replaceAllUsesWith(NewPtrForOldDecl); - } - - // Ok, delete the old function now, which is dead. - GV->eraseFromParent(); - - GV = NewFn; - } // We need to set linkage and visibility on the function before // generating code for it because various parts of IR generation Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -3300,7 +3300,7 @@ if (CGType == StructorCodegen::RAUW) { StringRef MangledName = CGM.getMangledName(CompleteDecl); - auto *Aliasee = cast(CGM.GetAddrOfGlobal(BaseDecl)); + auto *Aliasee = CGM.GetAddrOfGlobal(BaseDecl); CGM.addReplacement(MangledName, Aliasee); return; } Index: test/CodeGenCXX/duplicate-mangled-name.cpp =================================================================== --- test/CodeGenCXX/duplicate-mangled-name.cpp +++ test/CodeGenCXX/duplicate-mangled-name.cpp @@ -6,5 +6,28 @@ }; void MyClass::meth() { } // expected-note {{previous}} extern "C" { - void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}} + void _ZN7MyClass4methEv() { } // expected-warning {{definition with same mangled name as another definition}} } + +// We expect no warnings here, as there is only declaration of _ZN1TD1Ev function, no definitions. +extern "C" void _ZN1TD1Ev(); +struct T { + ~T() {} +}; + +void foo() { + _ZN1TD1Ev(); + T t; +} + +extern "C" void _ZN2T2D2Ev() {}; // expected-note {{previous definition is here}} + +struct T2 { + ~T2() {} // expected-warning {{definition with same mangled name as another definition}} +}; + +void bar() { + _ZN2T2D2Ev(); + T2 t; +} +