summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Decl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/Decl.cpp')
-rw-r--r--clang/lib/AST/Decl.cpp41
1 files changed, 40 insertions, 1 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index b8f478728f0..cbd55889c9e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -273,6 +273,45 @@ getLVForTemplateParameterList(const TemplateParameterList *params) {
static LinkageInfo getLVForDecl(const NamedDecl *D,
LVComputationKind computation);
+static const FunctionDecl *getOutermostFunctionContext(const Decl *D) {
+ const FunctionDecl *Ret = NULL;
+ const DeclContext *DC = D->getDeclContext();
+ while (DC->getDeclKind() != Decl::TranslationUnit) {
+ const FunctionDecl *F = dyn_cast<FunctionDecl>(DC);
+ if (F)
+ Ret = F;
+ DC = DC->getParent();
+ }
+ return Ret;
+}
+
+/// Get the linkage and visibility to be used when this type is a template
+/// argument. This is normally just the linkage and visibility of the type,
+/// but for function local types we need to check the linkage and visibility
+/// of the function.
+static LinkageInfo getLIForTemplateTypeArgument(QualType T) {
+ LinkageInfo LI = T->getLinkageAndVisibility();
+ if (LI.getLinkage() != NoLinkage)
+ return LI;
+
+ const TagType *TT = dyn_cast<TagType>(T);
+ if (!TT)
+ return LI;
+
+ const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TT->getDecl());
+ if (!RD)
+ return LI;
+
+ const FunctionDecl *FD = getOutermostFunctionContext(RD);
+ if (!FD)
+ return LI;
+
+ if (!FD->isInlined())
+ return LI;
+
+ return FD->getLinkageAndVisibility();
+}
+
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
///
@@ -291,7 +330,7 @@ getLVForTemplateArgumentList(ArrayRef<TemplateArgument> args) {
continue;
case TemplateArgument::Type:
- LV.merge(arg.getAsType()->getLinkageAndVisibility());
+ LV.merge(getLIForTemplateTypeArgument(arg.getAsType()));
continue;
case TemplateArgument::Declaration:
OpenPOWER on IntegriCloud