summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGDebugInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp94
1 files changed, 83 insertions, 11 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 8ba69eaa5c5..b2a3f7e0e98 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2374,6 +2374,58 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile &Unit,
: VD->getDeclContext()));
}
+llvm::DISubprogram
+CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) {
+ llvm::DIArray TParamsArray;
+ StringRef Name, LinkageName;
+ unsigned Flags = 0;
+ SourceLocation Loc = FD->getLocation();
+ llvm::DIFile Unit = getOrCreateFile(Loc);
+ llvm::DIDescriptor DContext(Unit);
+ unsigned Line = getLineNumber(Loc);
+
+ collectFunctionDeclProps(FD, Unit, Name, LinkageName, DContext,
+ TParamsArray, Flags);
+ // Build function type.
+ SmallVector<QualType, 16> ArgTypes;
+ for (const ParmVarDecl *Parm: FD->parameters())
+ ArgTypes.push_back(Parm->getType());
+ QualType FnType =
+ CGM.getContext().getFunctionType(FD->getReturnType(), ArgTypes,
+ FunctionProtoType::ExtProtoInfo());
+ llvm::DISubprogram SP =
+ DBuilder.createTempFunctionFwdDecl(DContext, Name, LinkageName, Unit, Line,
+ getOrCreateFunctionType(FD, FnType, Unit),
+ !FD->isExternallyVisible(),
+ false /*declaration*/, 0, Flags,
+ CGM.getLangOpts().Optimize, nullptr,
+ TParamsArray, getFunctionDeclaration(FD));
+ const FunctionDecl *CanonDecl = cast<FunctionDecl>(FD->getCanonicalDecl());
+ FwdDeclReplaceMap.push_back(std::make_pair(CanonDecl,
+ static_cast<llvm::Value *>(SP)));
+ return SP;
+}
+
+llvm::DIGlobalVariable
+CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) {
+ QualType T;
+ StringRef Name, LinkageName;
+ SourceLocation Loc = VD->getLocation();
+ llvm::DIFile Unit = getOrCreateFile(Loc);
+ llvm::DIDescriptor DContext(Unit);
+ unsigned Line = getLineNumber(Loc);
+
+ collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext);
+ llvm::DIGlobalVariable GV =
+ DBuilder.createTempGlobalVariableFwdDecl(DContext, Name, LinkageName, Unit,
+ Line, getOrCreateType(T, Unit),
+ !VD->isExternallyVisible(),
+ nullptr, nullptr);
+ FwdDeclReplaceMap.push_back(std::make_pair(cast<VarDecl>(VD->getCanonicalDecl()),
+ static_cast<llvm::Value *>(GV)));
+ return GV;
+}
+
llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
// We only need a declaration (not a definition) of the type - so use whatever
// we would otherwise do to get a type for a pointee. (forward declarations in
@@ -2382,19 +2434,22 @@ llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
return getOrCreateType(CGM.getContext().getTypeDeclType(TD),
getOrCreateFile(TD->getLocation()));
- // Otherwise fall back to a fairly rudimentary cache of existing declarations.
- // This doesn't handle providing declarations (for functions or variables) for
- // entities without definitions in this TU, nor when the definition proceeds
- // the call to this function.
- // FIXME: This should be split out into more specific maps with support for
- // emitting forward declarations and merging definitions with declarations,
- // the same way as we do for types.
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator I =
DeclCache.find(D->getCanonicalDecl());
- if (I == DeclCache.end())
- return llvm::DIScope();
- llvm::Value *V = I->second;
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
+
+ if (I != DeclCache.end()) {
+ llvm::Value *V = I->second;
+ return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
+ }
+
+ // No definition for now. Emit a forward definition that might be
+ // merged with a potential upcoming definition.
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ return getFunctionForwardDeclaration(FD);
+ else if (const auto *VD = dyn_cast<VarDecl>(D))
+ return getGlobalVariableForwardDeclaration(VD);
+
+ return llvm::DIDescriptor();
}
/// getFunctionDeclaration - Return debug info descriptor to describe method
@@ -3330,6 +3385,23 @@ void CGDebugInfo::finalize() {
Ty.replaceAllUsesWith(CGM.getLLVMContext(), RepTy);
}
+ for (const auto &p : FwdDeclReplaceMap) {
+ assert(p.second);
+ llvm::DIDescriptor FwdDecl(cast<llvm::MDNode>(p.second));
+ llvm::WeakVH VH;
+
+ auto it = DeclCache.find(p.first);
+ // If there has been no definition for the declaration, call RAUV
+ // with ourselves, that will destroy the temporary MDNode and
+ // replace it with a standard one, avoiding leaking memory.
+ if (it == DeclCache.end())
+ VH = p.second;
+ else
+ VH = it->second;
+ FwdDecl.replaceAllUsesWith(CGM.getLLVMContext(),
+ llvm::DIDescriptor(cast<llvm::MDNode>(VH)));
+ }
+
// We keep our own list of retained types, because we need to look
// up the final type in the type cache.
for (std::vector<void *>::const_iterator RI = RetainedTypes.begin(),
OpenPOWER on IntegriCloud