diff mbox series

[committed] d: Merge bug fix from upstream dmd 06160ccae

Message ID 20200429084507.21601-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge bug fix from upstream dmd 06160ccae | expand

Commit Message

Iain Buclaw April 29, 2020, 8:45 a.m. UTC
Hi,

This patch adds classKind information to the front-end AST, which in
turn allows us to fix code generation of type names for extern(C) and
extern(C++) structs and classes.  Inspecting such types inside a
debugger now just works without the need to cast(module_name.cxx).

Bootstrapped on x86_64-linux-gnu, committed to mainline.

Regards
Iain.

---
gcc/d/ChangeLog:

	* d-codegen.cc (d_decl_context): Don't include module in the name of
	class and struct types that aren't extern(D).
---
 gcc/d/d-codegen.cc                            |  4 ++-
 gcc/d/dmd/MERGE                               |  2 +-
 gcc/d/dmd/aggregate.h                         | 17 ++++++++--
 gcc/d/dmd/dclass.c                            | 32 +++++++++----------
 gcc/d/dmd/declaration.c                       |  2 +-
 gcc/d/dmd/dstruct.c                           |  4 +++
 gcc/d/dmd/func.c                              |  4 +--
 gcc/d/dmd/opover.c                            |  2 +-
 gcc/d/dmd/traits.c                            | 24 ++++++++++++--
 gcc/testsuite/gdc.test/compilable/test17419.d | 18 +++++++++++
 10 files changed, 82 insertions(+), 27 deletions(-)
diff mbox series

Patch

diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 12c6f138362..b4927a2de10 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -66,6 +66,7 @@  d_decl_context (Dsymbol *dsym)
 {
   Dsymbol *parent = dsym;
   Declaration *decl = dsym->isDeclaration ();
+  AggregateDeclaration *ad = dsym->isAggregateDeclaration ();
 
   while ((parent = parent->toParent2 ()))
     {
@@ -74,7 +75,8 @@  d_decl_context (Dsymbol *dsym)
 	 but only for extern(D) symbols.  */
       if (parent->isModule ())
 	{
-	  if (decl != NULL && decl->linkage != LINKd)
+	  if ((decl != NULL && decl->linkage != LINKd)
+	      || (ad != NULL && ad->classKind != ClassKind::d))
 	    return NULL_TREE;
 
 	  return build_import_decl (parent);
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index f933cf1c992..a2699d39842 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-f8a1a515346b16ebbd9da56a908540cbef1ee582
+06160ccaed7af7955d169024f417c43beb7a8f9f
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 881be58f2b8..da4a0398522 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -71,6 +71,19 @@  FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc);
 FuncDeclaration *buildInv(AggregateDeclaration *ad, Scope *sc);
 FuncDeclaration *search_toString(StructDeclaration *sd);
 
+struct ClassKind
+{
+    enum Type
+    {
+        /// the class is a d(efault) class
+        d,
+        /// the class is a C++ interface
+        cpp,
+        /// the class is an Objective-C class/interface
+        objc,
+    };
+};
+
 class AggregateDeclaration : public ScopeDsymbol
 {
 public:
@@ -84,6 +97,8 @@  public:
     Dsymbol *deferred;          // any deferred semantic2() or semantic3() symbol
     bool isdeprecated;          // true if deprecated
 
+    ClassKind::Type classKind;  // specifies the linkage type
+
     /* !=NULL if is nested
      * pointing to the dsymbol that directly enclosing it.
      * 1. The function that enclosing it (nested struct and class)
@@ -274,8 +289,6 @@  public:
 
     TypeInfoClassDeclaration *vclassinfo;       // the ClassInfo object for this ClassDeclaration
     bool com;                           // true if this is a COM class (meaning it derives from IUnknown)
-    bool cpp;                           // true if this is a C++ interface
-    bool isobjc;                        // true if this is an Objective-C class/interface
     bool isscope;                       // true if this is a scope class
     Abstract isabstract;                // 0: fwdref, 1: is abstract class, 2: not abstract
     int inuse;                          // to prevent recursive attempts
diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c
index 4609d6a9f54..a2009a604a5 100644
--- a/gcc/d/dmd/dclass.c
+++ b/gcc/d/dmd/dclass.c
@@ -240,12 +240,10 @@  ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
     }
 
     com = false;
-    cpp = false;
     isscope = false;
     isabstract = ABSfwdref;
     inuse = 0;
     baseok = BASEOKnone;
-    isobjc = false;
     cpp_type_info_ptr_sym = NULL;
 }
 
@@ -389,7 +387,7 @@  void ClassDeclaration::semantic(Scope *sc)
         userAttribDecl = sc->userAttribDecl;
 
         if (sc->linkage == LINKcpp)
-            cpp = true;
+            classKind = ClassKind::cpp;
         if (sc->linkage == LINKobjc)
             objc()->setObjc(this);
     }
@@ -555,7 +553,7 @@  void ClassDeclaration::semantic(Scope *sc)
         baseok = BASEOKdone;
 
         // If no base class, and this is not an Object, use Object as base class
-        if (!baseClass && ident != Id::Object && !cpp)
+        if (!baseClass && ident != Id::Object && !isCPPclass())
         {
             if (!object || object->errors)
                 badObjectDotD(this);
@@ -583,7 +581,7 @@  void ClassDeclaration::semantic(Scope *sc)
             if (baseClass->isCOMclass())
                 com = true;
             if (baseClass->isCPPclass())
-                cpp = true;
+                classKind = ClassKind::cpp;
             if (baseClass->isscope)
                 isscope = true;
             enclosing = baseClass->enclosing;
@@ -600,7 +598,7 @@  void ClassDeclaration::semantic(Scope *sc)
             // then this is a COM interface too.
             if (b->sym->isCOMinterface())
                 com = true;
-            if (cpp && !b->sym->isCPPinterface())
+            if (isCPPclass() && !b->sym->isCPPinterface())
             {
                 ::error(loc, "C++ class '%s' cannot implement D interface '%s'",
                     toPrettyChars(), b->sym->toPrettyChars());
@@ -675,7 +673,7 @@  Lancestorsdone:
         // initialize vtbl
         if (baseClass)
         {
-            if (cpp && baseClass->vtbl.dim == 0)
+            if (isCPPclass() && baseClass->vtbl.dim == 0)
             {
                 error("C++ base class %s needs at least one virtual function", baseClass->toChars());
             }
@@ -1087,7 +1085,7 @@  void ClassDeclaration::finalizeSize()
 
         alignsize = baseClass->alignsize;
         structsize = baseClass->structsize;
-        if (cpp && global.params.isWindows)
+        if (isCPPclass() && global.params.isWindows)
             structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
     }
     else if (isInterfaceDeclaration())
@@ -1102,7 +1100,7 @@  void ClassDeclaration::finalizeSize()
     {
         alignsize = Target::ptrsize;
         structsize = Target::ptrsize;      // allow room for __vptr
-        if (!cpp)
+        if (!isCPPclass())
             structsize += Target::ptrsize; // allow room for __monitor
     }
 
@@ -1299,7 +1297,7 @@  bool ClassDeclaration::isCOMinterface() const
 
 bool ClassDeclaration::isCPPclass() const
 {
-    return cpp;
+    return classKind == ClassKind::cpp;
 }
 
 bool ClassDeclaration::isCPPinterface() const
@@ -1378,7 +1376,7 @@  bool ClassDeclaration::isAbstract()
 
 int ClassDeclaration::vtblOffset() const
 {
-    return cpp ? 0 : 1;
+    return classKind == ClassKind::cpp ? 0 : 1;
 }
 
 /****************************************
@@ -1405,7 +1403,7 @@  InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses
     if (id == Id::IUnknown)     // IUnknown is the root of all COM interfaces
     {
         com = true;
-        cpp = true;             // IUnknown is also a C++ interface
+        classKind = ClassKind::cpp; // IUnknown is also a C++ interface
     }
 }
 
@@ -1422,9 +1420,9 @@  Scope *InterfaceDeclaration::newScope(Scope *sc)
     Scope *sc2 = ClassDeclaration::newScope(sc);
     if (com)
         sc2->linkage = LINKwindows;
-    else if (cpp)
+    else if (classKind == ClassKind::cpp)
         sc2->linkage = LINKcpp;
-    else if (isobjc)
+    else if (classKind == ClassKind::objc)
         sc2->linkage = LINKobjc;
     return sc2;
 }
@@ -1523,7 +1521,7 @@  void InterfaceDeclaration::semantic(Scope *sc)
         }
 
         if (!baseclasses->dim && sc->linkage == LINKcpp)
-            cpp = true;
+            classKind = ClassKind::cpp;
         if (sc->linkage == LINKobjc)
             objc()->setObjc(this);
 
@@ -1605,7 +1603,7 @@  void InterfaceDeclaration::semantic(Scope *sc)
             if (b->sym->isCOMinterface())
                 com = true;
             if (b->sym->isCPPinterface())
-                cpp = true;
+                classKind = ClassKind::cpp;
         }
 
         interfaceSemantic(sc);
@@ -1817,7 +1815,7 @@  bool InterfaceDeclaration::isCOMinterface() const
 
 bool InterfaceDeclaration::isCPPinterface() const
 {
-    return cpp;
+    return classKind == ClassKind::cpp;
 }
 
 /*******************************************
diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c
index 806e29d6907..2ad6af2d410 100644
--- a/gcc/d/dmd/declaration.c
+++ b/gcc/d/dmd/declaration.c
@@ -2174,7 +2174,7 @@  Expression *VarDeclaration::callScopeDtor(Scope *)
 
             // Destroying C++ scope classes crashes currently. Since C++ class dtors are not currently supported, simply do not run dtors for them.
             // See https://issues.dlang.org/show_bug.cgi?id=13182
-            if (cd->cpp)
+            if (cd->isCPPclass())
             {
                 break;
             }
diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c
index 10771c95a07..0a33cc23935 100644
--- a/gcc/d/dmd/dstruct.c
+++ b/gcc/d/dmd/dstruct.c
@@ -194,6 +194,7 @@  AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
     sizeok = SIZEOKnone;        // size not determined yet
     deferred = NULL;
     isdeprecated = false;
+    classKind = ClassKind::d;
     inv = NULL;
     aggNew = NULL;
     aggDelete = NULL;
@@ -1071,6 +1072,9 @@  void StructDeclaration::semantic(Scope *sc)
         if (storage_class & STCabstract)
             error("structs, unions cannot be abstract");
         userAttribDecl = sc->userAttribDecl;
+
+        if (sc->linkage == LINKcpp)
+            classKind = ClassKind::cpp;
     }
     else if (symtab && !scx)
     {
diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c
index ab74dc5328b..621405eef3e 100644
--- a/gcc/d/dmd/func.c
+++ b/gcc/d/dmd/func.c
@@ -876,7 +876,7 @@  void FuncDeclaration::semantic(Scope *sc)
 
                 /* These quirky conditions mimic what VC++ appears to do
                  */
-                if (global.params.mscoff && cd->cpp &&
+                if (global.params.mscoff && cd->isCPPclass() &&
                     cd->baseClass && cd->baseClass->vtbl.dim)
                 {
                     /* if overriding an interface function, then this is not
@@ -902,7 +902,7 @@  void FuncDeclaration::semantic(Scope *sc)
                 {
                     //printf("\tintroducing function %s\n", toChars());
                     introducing = 1;
-                    if (cd->cpp && Target::reverseCppOverloads)
+                    if (cd->isCPPclass() && Target::reverseCppOverloads)
                     {
                         // with dmc, overloaded functions are grouped and in reverse order
                         vtblIndex = (int)cd->vtbl.dim;
diff --git a/gcc/d/dmd/opover.c b/gcc/d/dmd/opover.c
index b3ea6cf4671..e1ff5e9913b 100644
--- a/gcc/d/dmd/opover.c
+++ b/gcc/d/dmd/opover.c
@@ -962,7 +962,7 @@  Expression *op_overload(Expression *e, Scope *sc)
                 ClassDeclaration *cd1 = t1->isClassHandle();
                 ClassDeclaration *cd2 = t2->isClassHandle();
 
-                if (!(cd1->cpp || cd2->cpp))
+                if (!(cd1->isCPPclass() || cd2->isCPPclass()))
                 {
                     /* Rewrite as:
                      *      .object.opEquals(e1, e2)
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index 04726c36473..535893feffb 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -1135,12 +1135,32 @@  Expression *semanticTraits(TraitsExp *e, Scope *sc)
         {
             Dsymbol *s = getDsymbol(o);
             Declaration *d = NULL;
-            if (!s || (d = s->isDeclaration()) == NULL)
+            AggregateDeclaration *ad = NULL;
+            if (!s || ((d = s->isDeclaration()) == NULL
+                       && (ad = s->isAggregateDeclaration()) == NULL))
             {
                 e->error("argument to `__traits(getLinkage, %s)` is not a declaration", o->toChars());
                 return new ErrorExp();
             }
-            link = d->linkage;
+            if (d != NULL)
+                link = d->linkage;
+            else
+            {
+                switch (ad->classKind)
+                {
+                    case ClassKind::d:
+                        link = LINKd;
+                        break;
+                    case ClassKind::cpp:
+                        link = LINKcpp;
+                        break;
+                    case ClassKind::objc:
+                        link = LINKobjc;
+                        break;
+                    default:
+                        assert(0);
+                }
+            }
         }
         const char *linkage = linkageToChars(link);
         StringExp *se = new StringExp(e->loc, const_cast<char *>(linkage));
diff --git a/gcc/testsuite/gdc.test/compilable/test17419.d b/gcc/testsuite/gdc.test/compilable/test17419.d
index 219ed4f712e..d67c5b96d5a 100644
--- a/gcc/testsuite/gdc.test/compilable/test17419.d
+++ b/gcc/testsuite/gdc.test/compilable/test17419.d
@@ -35,3 +35,21 @@  void bar()
     void nested() { }
     static assert(__traits(getLinkage, typeof(&nested)) == "D");
 }
+
+class FooD {}
+interface FooDInterface {}
+extern (C++) class FooCpp {}
+extern (C++) struct FooCppStruct {}
+extern (C++) interface FooCppInterface {}
+
+static assert(__traits(getLinkage, FooD) == "D");
+static assert(__traits(getLinkage, FooDInterface) == "D");
+static assert(__traits(getLinkage, FooCpp) == "C++");
+static assert(__traits(getLinkage, FooCppStruct) == "C++");
+static assert(__traits(getLinkage, FooCppInterface) == "C++");
+
+version (D_ObjectiveC)
+{
+    extern (Objective-C) interface FooObjC {}
+    static assert(__traits(getLinkage, FooObjC) == "Objective-C");
+}