r323935 - PR36181: Teach CodeGen to properly ignore requests to emit dependent entities.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 31 16:28:36 PST 2018


Author: rsmith
Date: Wed Jan 31 16:28:36 2018
New Revision: 323935

URL: http://llvm.org/viewvc/llvm-project?rev=323935&view=rev
Log:
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.

Added:
    cfe/trunk/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=323935&r1=323934&r2=323935&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Wed Jan 31 16:28:36 2018
@@ -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

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=323935&r1=323934&r2=323935&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Wed Jan 31 16:28:36 2018
@@ -236,10 +236,23 @@ TemplateDecl *Decl::getDescribedTemplate
     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(); 

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=323935&r1=323934&r2=323935&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Jan 31 16:28:36 2018
@@ -4190,18 +4190,13 @@ void CodeGenModule::EmitDeclContext(cons
 /// 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.
@@ -4214,10 +4209,6 @@ void CodeGenModule::EmitTopLevelDecl(Dec
 
   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))
@@ -4276,16 +4267,9 @@ void CodeGenModule::EmitTopLevelDecl(Dec
       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;
 

Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp?rev=323935&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-emit-dependent.cpp Wed Jan 31 16:28:36 2018
@@ -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>()); }




More information about the cfe-commits mailing list