diff options
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 113 |
1 files changed, 86 insertions, 27 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 97b166278f8..41a4a1212ea 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1244,19 +1244,23 @@ void CodeGenModule::EmitDeferred() { for (DeferredGlobal &G : CurDeclsToEmit) { GlobalDecl D = G.GD; - llvm::GlobalValue *GV = G.GV; G.GV = nullptr; // 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<FunctionDecl>(D.getDecl())) - GV = cast<llvm::GlobalValue>(GetAddrOfGlobal(D, /*IsForDefinition=*/true)); - else - if (!GV) - GV = GetGlobalValue(getMangledName(D)); + llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>( + GetAddrOfGlobal(D, /*IsForDefinition=*/true)); + + // In case of different address spaces, we may still get a cast, even with + // IsForDefinition equal to true. Query mangled names table to get + // GlobalValue. + if (!GV) + GV = GetGlobalValue(getMangledName(D)); + + // Make sure GetGlobalValue returned non-null. + assert(GV); // Check to see if we've already emitted this. This is necessary // for a couple of reasons: first, decls can end up in the @@ -1264,7 +1268,7 @@ void CodeGenModule::EmitDeferred() { // up with definitions in unusual ways (e.g. by an extern inline // function acquiring a strong function redefinition). Just // ignore these cases. - if (GV && !GV->isDeclaration()) + if (!GV->isDeclaration()) continue; // Otherwise, emit the definition and move on to the next one. @@ -1730,7 +1734,7 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { } if (const auto *VD = dyn_cast<VarDecl>(D)) - return EmitGlobalVarDefinition(VD); + return EmitGlobalVarDefinition(VD, !VD->hasDefinition()); llvm_unreachable("Invalid argument to EmitGlobalDefinition()"); } @@ -1771,8 +1775,8 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, // error. if (IsForDefinition && !Entry->isDeclaration()) { GlobalDecl OtherGD; - // Check that GD is not yet in ExplicitDefinitions is required to make - // sure that we issue an error only once. + // Check that GD is not yet in DiagnosedConflictingDefinitions is required + // to make sure that we issue an error only once. if (lookupRepresentativeDecl(MangledName, OtherGD) && (GD.getCanonicalDecl().getDecl() != OtherGD.getCanonicalDecl().getDecl()) && @@ -1982,10 +1986,15 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { /// /// If D is non-null, it specifies a decl that correspond to this. This is used /// to set the attributes on the global when it is first created. +/// +/// If IsForDefinition is true, it is guranteed that an actual global with +/// type Ty will be returned, not conversion of a variable with the same +/// mangled name but some other type. llvm::Constant * CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::PointerType *Ty, - const VarDecl *D) { + const VarDecl *D, + bool IsForDefinition) { // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *Entry = GetGlobalValue(MangledName); if (Entry) { @@ -2001,11 +2010,34 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, if (Entry->getType() == Ty) return Entry; + // If there are two attempts to define the same mangled name, issue an + // error. + if (IsForDefinition && !Entry->isDeclaration()) { + GlobalDecl OtherGD; + const VarDecl *OtherD; + + // Check that D is not yet in DiagnosedConflictingDefinitions is required + // to make sure that we issue an error only once. + if (lookupRepresentativeDecl(MangledName, OtherGD) && + (D->getCanonicalDecl() != OtherGD.getCanonicalDecl().getDecl()) && + (OtherD = dyn_cast<VarDecl>(OtherGD.getDecl())) && + OtherD->hasInit() && + DiagnosedConflictingDefinitions.insert(D).second) { + getDiags().Report(D->getLocation(), + diag::err_duplicate_mangled_name); + getDiags().Report(OtherGD.getDecl()->getLocation(), + diag::note_previous_definition); + } + } + // Make sure the result is of the correct type. if (Entry->getType()->getAddressSpace() != Ty->getAddressSpace()) return llvm::ConstantExpr::getAddrSpaceCast(Entry, Ty); - return llvm::ConstantExpr::getBitCast(Entry, Ty); + // (If global is requested for a definition, we always need to create a new + // global, not just return a bitcast.) + if (!IsForDefinition) + return llvm::ConstantExpr::getBitCast(Entry, Ty); } unsigned AddrSpace = GetGlobalVarAddressSpace(D, Ty->getAddressSpace()); @@ -2014,6 +2046,20 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::GlobalValue::ExternalLinkage, nullptr, MangledName, nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace); + // If we already created a global with the same mangled name (but different + // type) before, take its name and remove it from its parent. + if (Entry) { + GV->takeName(Entry); + + if (!Entry->use_empty()) { + llvm::Constant *NewPtrForOldDecl = + llvm::ConstantExpr::getBitCast(GV, Entry->getType()); + Entry->replaceAllUsesWith(NewPtrForOldDecl); + } + + Entry->eraseFromParent(); + } + // This is the first use or definition of a mangled name. If there is a // deferred decl with this name, remember that we need to emit it at the end // of the file. @@ -2086,7 +2132,8 @@ CodeGenModule::GetAddrOfGlobal(GlobalDecl GD, return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false, IsForDefinition); } else - return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl())); + return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl()), /*Ty=*/nullptr, + IsForDefinition); } llvm::GlobalVariable * @@ -2134,9 +2181,12 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name, /// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the /// given global variable. If Ty is non-null and if the global doesn't exist, /// then it will be created with the specified type instead of whatever the -/// normal requested type would be. +/// normal requested type would be. If IsForDefinition is true, it is guranteed +/// that an actual global with type Ty will be returned, not conversion of a +/// variable with the same mangled name but some other type. llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, - llvm::Type *Ty) { + llvm::Type *Ty, + bool IsForDefinition) { assert(D->hasGlobalStorage() && "Not a global variable"); QualType ASTTy = D->getType(); if (!Ty) @@ -2146,7 +2196,7 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy)); StringRef MangledName = getMangledName(D); - return GetOrCreateLLVMGlobal(MangledName, PTy, D); + return GetOrCreateLLVMGlobal(MangledName, PTy, D, IsForDefinition); } /// CreateRuntimeVariable - Create a new runtime global variable with the @@ -2160,15 +2210,20 @@ CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty, void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { assert(!D->getInit() && "Cannot emit definite definitions here!"); - if (!MustBeEmitted(D)) { - // If we have not seen a reference to this variable yet, place it - // into the deferred declarations table to be emitted if needed - // later. - StringRef MangledName = getMangledName(D); - if (!GetGlobalValue(MangledName)) { + StringRef MangledName = getMangledName(D); + llvm::GlobalValue *GV = GetGlobalValue(MangledName); + + // We already have a definition, not declaration, with the same mangled name. + // Emitting of declaration is not required (and actually overwrites emitted + // definition). + if (GV && !GV->isDeclaration()) + return; + + // If we have not seen a reference to this variable yet, place it into the + // deferred declarations table to be emitted if needed later. + if (!MustBeEmitted(D) && !GV) { DeferredDecls[MangledName] = D; return; - } } // The tentative definition is the only definition. @@ -2259,7 +2314,9 @@ void CodeGenModule::maybeSetTrivialComdat(const Decl &D, GO.setComdat(TheModule.getOrInsertComdat(GO.getName())); } -void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { +/// Pass IsTentative as true if you want to create a tentative definition. +void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, + bool IsTentative) { llvm::Constant *Init = nullptr; QualType ASTTy = D->getType(); CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); @@ -2318,7 +2375,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { } llvm::Type* InitType = Init->getType(); - llvm::Constant *Entry = GetAddrOfGlobalVar(D, InitType); + llvm::Constant *Entry = + GetAddrOfGlobalVar(D, InitType, /*IsForDefinition=*/!IsTentative); // Strip off a bitcast if we got one back. if (auto *CE = dyn_cast<llvm::ConstantExpr>(Entry)) { @@ -2350,7 +2408,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { Entry->setName(StringRef()); // Make a new global with the correct type, this is now guaranteed to work. - GV = cast<llvm::GlobalVariable>(GetAddrOfGlobalVar(D, InitType)); + GV = cast<llvm::GlobalVariable>( + GetAddrOfGlobalVar(D, InitType, /*IsForDefinition=*/!IsTentative)); // Replace all uses of the old global with the new global llvm::Constant *NewPtrForOldDecl = |