From 158255398cdb2bd186c8dc1b8ce7817ac82c29d8 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 1 Feb 2018 00:28:36 +0000 Subject: [PATCH] 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/trunk@323935 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclBase.h | 4 ++++ lib/AST/DeclBase.cpp | 13 +++++++++++++ lib/CodeGen/CodeGenModule.cpp | 18 +----------------- .../microsoft-abi-emit-dependent.cpp | 11 +++++++++++ 4 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 test/CodeGenCXX/microsoft-abi-emit-dependent.cpp diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index f17c34e26b..908894c133 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 18aa53b857..04fd62f738 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(this)) return VD->getDescribedVarTemplate(); + else if (auto *AD = dyn_cast(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(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 eba886db3e..760327deb1 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -4190,18 +4190,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(D)->getDescribedFunctionTemplate() || - cast(D)->isLateTemplateParsed()) - return; - EmitGlobal(cast(D)); // Always provide some coverage mapping // even for the functions that aren't emitted. @@ -4214,10 +4209,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::Var: case Decl::Decomposition: - // Skip variable templates - if (cast(D)->getDescribedVarTemplate()) - return; - LLVM_FALLTHROUGH; case Decl::VarTemplateSpecialization: EmitGlobal(cast(D)); if (auto *DD = dyn_cast(D)) @@ -4276,16 +4267,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { DI->EmitUsingDirective(cast(*D)); return; case Decl::CXXConstructor: - // Skip function templates - if (cast(D)->getDescribedFunctionTemplate() || - cast(D)->isLateTemplateParsed()) - return; - getCXXABI().EmitCXXConstructors(cast(D)); break; case Decl::CXXDestructor: - if (cast(D)->isLateTemplateParsed()) - return; getCXXABI().EmitCXXDestructors(cast(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 struct A { + friend void f(A) {} +}; +#pragma clang module endbuild +#pragma clang module import foo +void g() { f(A()); } -- 2.40.0