summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-02-05 09:29:08 +0000
committerHans Wennborg <hans@hanshq.net>2018-02-05 09:29:08 +0000
commiteb51f1dc7cd9d8c95a09b991454af77e2dc055a3 (patch)
treeae186926c3abad24b898d1070315bbca742915d0
parent2f7bb0ceae436c56d0e88c7a0215e6b072d86576 (diff)
Merging r323935:
------------------------------------------------------------------------ r323935 | rsmith | 2018-02-01 01:28:36 +0100 (Thu, 01 Feb 2018) | 5 lines PR36181: Teach CodeGen to properly ignore requests to emit dependent entities. Previously, friend function definitions within class templates slipped through the gaps and caused the MS mangler to assert. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_60@324215 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/DeclBase.h4
-rw-r--r--lib/AST/DeclBase.cpp13
-rw-r--r--lib/CodeGen/CodeGenModule.cpp18
-rw-r--r--test/CodeGenCXX/microsoft-abi-emit-dependent.cpp11
4 files changed, 29 insertions, 17 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index f93c9f0b9a..15de482a86 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -836,6 +836,10 @@ public:
void setLexicalDeclContext(DeclContext *DC);
+ /// Determine whether this declaration is a templated entity (whether it is
+ // within the scope of a template parameter).
+ bool isTemplated() const;
+
/// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
/// scoped decl is defined outside the current function or method. This is
/// roughly global variables and functions, but also handles enums (which
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 2cdcdae9ab..d427c79c44 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -236,10 +236,23 @@ TemplateDecl *Decl::getDescribedTemplate() const {
return RD->getDescribedClassTemplate();
else if (auto *VD = dyn_cast<VarDecl>(this))
return VD->getDescribedVarTemplate();
+ else if (auto *AD = dyn_cast<TypeAliasDecl>(this))
+ return AD->getDescribedAliasTemplate();
return nullptr;
}
+bool Decl::isTemplated() const {
+ // A declaration is dependent if it is a template or a template pattern, or
+ // is within (lexcially for a friend, semantically otherwise) a dependent
+ // context.
+ // FIXME: Should local extern declarations be treated like friends?
+ if (auto *AsDC = dyn_cast<DeclContext>(this))
+ return AsDC->isDependentContext();
+ auto *DC = getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
+ return DC->isDependentContext() || isTemplateDecl() || getDescribedTemplate();
+}
+
const DeclContext *Decl::getParentFunctionOrMethod() const {
for (const DeclContext *DC = getDeclContext();
DC && !DC->isTranslationUnit() && !DC->isNamespace();
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index df33fc3e82..2172486682 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -4000,18 +4000,13 @@ void CodeGenModule::EmitDeclContext(const DeclContext *DC) {
/// EmitTopLevelDecl - Emit code for a single top level declaration.
void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// Ignore dependent declarations.
- if (D->getDeclContext() && D->getDeclContext()->isDependentContext())
+ if (D->isTemplated())
return;
switch (D->getKind()) {
case Decl::CXXConversion:
case Decl::CXXMethod:
case Decl::Function:
- // Skip function templates
- if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
- cast<FunctionDecl>(D)->isLateTemplateParsed())
- return;
-
EmitGlobal(cast<FunctionDecl>(D));
// Always provide some coverage mapping
// even for the functions that aren't emitted.
@@ -4024,10 +4019,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::Var:
case Decl::Decomposition:
- // Skip variable templates
- if (cast<VarDecl>(D)->getDescribedVarTemplate())
- return;
- LLVM_FALLTHROUGH;
case Decl::VarTemplateSpecialization:
EmitGlobal(cast<VarDecl>(D));
if (auto *DD = dyn_cast<DecompositionDecl>(D))
@@ -4086,16 +4077,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
DI->EmitUsingDirective(cast<UsingDirectiveDecl>(*D));
return;
case Decl::CXXConstructor:
- // Skip function templates
- if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
- cast<FunctionDecl>(D)->isLateTemplateParsed())
- return;
-
getCXXABI().EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
case Decl::CXXDestructor:
- if (cast<FunctionDecl>(D)->isLateTemplateParsed())
- return;
getCXXABI().EmitCXXDestructors(cast<CXXDestructorDecl>(D));
break;
diff --git a/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp b/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp
new file mode 100644
index 0000000000..e74ebc879f
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm-only -fmodules -triple x86_64-windows %s
+// PR36181
+#pragma clang module build foo
+module foo {}
+#pragma clang module contents
+template <typename T> struct A {
+ friend void f(A<T>) {}
+};
+#pragma clang module endbuild
+#pragma clang module import foo
+void g() { f(A<int>()); }