d: Merge bug fix from upstream dmd 06160ccae
authorIain Buclaw <ibuclaw@gdcproject.org>
Wed, 29 Apr 2020 08:19:55 +0000 (10:19 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Wed, 29 Apr 2020 08:36:00 +0000 (10:36 +0200)
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_type)'.

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/ChangeLog
gcc/d/d-codegen.cc
gcc/d/dmd/MERGE
gcc/d/dmd/aggregate.h
gcc/d/dmd/dclass.c
gcc/d/dmd/declaration.c
gcc/d/dmd/dstruct.c
gcc/d/dmd/func.c
gcc/d/dmd/opover.c
gcc/d/dmd/traits.c
gcc/testsuite/gdc.test/compilable/test17419.d

index 3b5fc12a8fd1515882dc3ebffffa818cc67d84b4..9550a6d581f2e78c012bb42b53ebdf231c654eb3 100644 (file)
@@ -1,3 +1,8 @@
+2020-04-29  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-codegen.cc (d_decl_context): Don't include module in the name of
+       class and struct types that aren't extern(D).
+
 2020-04-27  Iain Buclaw  <ibuclaw@gdcproject.org>
 
        PR d/94777
index 12c6f13836207d00c0afe4df5c1a6b4023b253df..b4927a2de10503c80f7c5fa385eb22ad436e8350 100644 (file)
@@ -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);
index f933cf1c9920cd8dd63350d27488729fccbebccb..a2699d39842c86b4b355d2995be42816eebd16b2 100644 (file)
@@ -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.
index 881be58f2b80949438fbe97bd906e69ae5f3b637..da4a039852258e7d7d674780071fabfcc1cbdb1f 100644 (file)
@@ -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
index 4609d6a9f54ddcb351531824e4350fa9d6e5fa93..a2009a604a56bd8f7eaa4a84cff80fc6da0ec7f4 100644 (file)
@@ -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;
 }
 
 /*******************************************
index 806e29d690738ce56e5327aaaacfc18067134523..2ad6af2d4104bc5fbc9236d5d46c0683bf7584be 100644 (file)
@@ -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;
             }
index 10771c95a07ff69f0c0ce9b206ff9443d038b5b3..0a33cc23935595826d55945630491e6c569d9ece 100644 (file)
@@ -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)
     {
index ab74dc5328b3ad7d43bbe6887fc67e925c626c64..621405eef3e27bf55612d69380ad6cd89b62d819 100644 (file)
@@ -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;
index b3ea6cf467184729e8860a16efca96f3aab9fbc2..e1ff5e9913bab3d9c508cfb4faada7ac1886dfc7 100644 (file)
@@ -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)
index 04726c36473e8d2722ccff30614b464ed78f6674..535893feffbe95cb679ebca27ec9d3f5bc40c1b3 100644 (file)
@@ -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));
index 219ed4f712e6c312f2c5238174320b91db1ab5ca..d67c5b96d5a983e38cc86c5cdb8f9b0b85fadce5 100644 (file)
@@ -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");
+}