r314037 - DR1113: anonymous namespaces formally give their contents internal linkage.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 22 16:36:18 PDT 2017


Investigating...

On 22 September 2017 at 15:58, Vitaly Buka via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> This breaks check-clang-tools
> http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_
> 64-scei-ps4-windows10pro-fast/builds/12310/steps/test/logs/stdio
>
> On Fri, Sep 22, 2017 at 3:21 PM, Richard Smith via cfe-commits <
> cfe-commits at lists.llvm.org> wrote:
>
>> Author: rsmith
>> Date: Fri Sep 22 15:21:44 2017
>> New Revision: 314037
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=314037&view=rev
>> Log:
>> DR1113: anonymous namespaces formally give their contents internal
>> linkage.
>>
>> This doesn't affect our code generation in any material way -- we already
>> give
>> such declarations internal linkage from a codegen perspective -- but it
>> has
>> some subtle effects on code validity.
>>
>> We suppress the 'L' (internal linkage) marker for mangled names in
>> anonymous
>> namespaces, because it is redundant (the information is already carried
>> by the
>> namespace); this deviates from GCC's behavior if a variable or function
>> in an
>> anonymous namespace is redundantly declared 'static' (where GCC does
>> include
>> the 'L'), but GCC's behavior is incoherent because such a declaration can
>> be
>> validly declared with or without the 'static'.
>>
>> We still deviate from the standard in one regard here: extern "C"
>> declarations
>> in anonymous namespaces are still granted external linkage. Changing
>> those does
>> not appear to have been an intentional consequence of the standard change
>> in
>> DR1113.
>>
>> Added:
>>     cfe/trunk/test/CXX/drs/dr11xx.cpp
>> Modified:
>>     cfe/trunk/lib/AST/Decl.cpp
>>     cfe/trunk/lib/AST/ItaniumMangle.cpp
>>     cfe/trunk/test/CXX/basic/basic.link/p8.cpp
>>     cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp
>>     cfe/trunk/test/SemaCXX/linkage2.cpp
>>     cfe/trunk/test/SemaCXX/undefined-internal.cpp
>>
>> Modified: cfe/trunk/lib/AST/Decl.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.
>> cpp?rev=314037&r1=314036&r2=314037&view=diff
>> ============================================================
>> ==================
>> --- cfe/trunk/lib/AST/Decl.cpp (original)
>> +++ cfe/trunk/lib/AST/Decl.cpp Fri Sep 22 15:21:44 2017
>> @@ -619,16 +619,16 @@ LinkageComputer::getLVForNamespaceScopeD
>>    if (D->isInAnonymousNamespace()) {
>>      const auto *Var = dyn_cast<VarDecl>(D);
>>      const auto *Func = dyn_cast<FunctionDecl>(D);
>> -    // FIXME: In C++11 onwards, anonymous namespaces should give decls
>> -    // within them (including those inside extern "C" contexts) internal
>> -    // linkage, not unique external linkage:
>> +    // FIXME: The check for extern "C" here is not justified by the
>> standard
>> +    // wording, but we retain it from the pre-DR1113 model to avoid
>> breaking
>> +    // code.
>>      //
>>      // C++11 [basic.link]p4:
>>      //   An unnamed namespace or a namespace declared directly or
>> indirectly
>>      //   within an unnamed namespace has internal linkage.
>>      if ((!Var || !isFirstInExternCContext(Var)) &&
>>          (!Func || !isFirstInExternCContext(Func)))
>> -      return LinkageInfo::uniqueExternal();
>> +      return getInternalLinkageFor(D);
>>    }
>>
>>    // Set up the defaults.
>> @@ -1130,7 +1130,7 @@ LinkageInfo LinkageComputer::getLVForLoc
>>    if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
>>      if (Function->isInAnonymousNamespace() &&
>>          !Function->isInExternCContext())
>> -      return LinkageInfo::uniqueExternal();
>> +      return getInternalLinkageFor(Function);
>>
>>      // This is a "void f();" which got merged with a file static.
>>      if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
>> @@ -1153,7 +1153,7 @@ LinkageInfo LinkageComputer::getLVForLoc
>>    if (const auto *Var = dyn_cast<VarDecl>(D)) {
>>      if (Var->hasExternalStorage()) {
>>        if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
>> -        return LinkageInfo::uniqueExternal();
>> +        return getInternalLinkageFor(Var);
>>
>>        LinkageInfo LV;
>>        if (Var->getStorageClass() == SC_PrivateExtern)
>>
>> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Itaniu
>> mMangle.cpp?rev=314037&r1=314036&r2=314037&view=diff
>> ============================================================
>> ==================
>> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
>> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Fri Sep 22 15:21:44 2017
>> @@ -1287,9 +1287,15 @@ void CXXNameMangler::mangleUnqualifiedNa
>>        //
>>        //   void test() { extern void foo(); }
>>        //   static void foo();
>> +      //
>> +      // Don't bother with the L marker for names in anonymous
>> namespaces; the
>> +      // 12_GLOBAL__N_1 mangling is quite sufficient there, and this
>> better
>> +      // matches GCC anyway, because GCC does not treat anonymous
>> namespaces as
>> +      // implying internal linkage.
>>        if (ND && ND->getFormalLinkage() == InternalLinkage &&
>>            !ND->isExternallyVisible() &&
>> -          getEffectiveDeclContext(ND)->isFileContext())
>> +          getEffectiveDeclContext(ND)->isFileContext() &&
>> +          !ND->isInAnonymousNamespace())
>>          Out << 'L';
>>
>>        auto *FD = dyn_cast<FunctionDecl>(ND);
>>
>> Modified: cfe/trunk/test/CXX/basic/basic.link/p8.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic
>> /basic.link/p8.cpp?rev=314037&r1=314036&r2=314037&view=diff
>> ============================================================
>> ==================
>> --- cfe/trunk/test/CXX/basic/basic.link/p8.cpp (original)
>> +++ cfe/trunk/test/CXX/basic/basic.link/p8.cpp Fri Sep 22 15:21:44 2017
>> @@ -52,6 +52,13 @@ void use_visible_no_linkage() {
>>    visible_no_linkage3(); // expected-note {{used here}}
>>  }
>>
>> +namespace {
>> +  struct InternalLinkage {};
>> +}
>> +InternalLinkage internal_linkage(); // expected-error {{used but not
>> defined}}
>> +void use_internal_linkage() {
>> +  internal_linkage(); // expected-note {{used here}}
>> +}
>>
>>  extern inline int not_defined; // expected-error {{not defined}}
>>  extern inline int defined_after_use;
>>
>> Added: cfe/trunk/test/CXX/drs/dr11xx.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/
>> dr11xx.cpp?rev=314037&view=auto
>> ============================================================
>> ==================
>> --- cfe/trunk/test/CXX/drs/dr11xx.cpp (added)
>> +++ cfe/trunk/test/CXX/drs/dr11xx.cpp Fri Sep 22 15:21:44 2017
>> @@ -0,0 +1,30 @@
>> +// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions
>> -pedantic-errors
>> +// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions
>> -pedantic-errors
>> +// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions
>> -pedantic-errors
>> +// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions
>> -pedantic-errors
>> +// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions
>> -pedantic-errors
>> +
>> +namespace dr1113 { // dr1113: partial
>> +  namespace named {
>> +    extern int a; // expected-note {{previous}}
>> +    static int a; // expected-error {{static declaration of 'a' follows
>> non-static}}
>> +  }
>> +  namespace {
>> +    extern int a;
>> +    static int a; // ok, both declarations have internal linkage
>> +    int b = a;
>> +  }
>> +
>> +  // FIXME: Per DR1113 and DR4, this is ill-formed due to ambiguity: the
>> second
>> +  // 'f' has internal linkage, and so does not have C language linkage,
>> so is
>> +  // not a redeclaration of the first 'f'.
>> +  //
>> +  // To avoid a breaking change here, Clang ignores the "internal
>> linkage" effect
>> +  // of anonymous namespaces on declarations declared within an 'extern
>> "C"'
>> +  // linkage-specification.
>> +  extern "C" void f();
>> +  namespace {
>> +    extern "C" void f();
>> +  }
>> +  void g() { f(); }
>> +}
>>
>> Modified: cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCX
>> X/anonymous-namespaces.cpp?rev=314037&r1=314036&r2=314037&view=diff
>> ============================================================
>> ==================
>> --- cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp (original)
>> +++ cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp Fri Sep 22
>> 15:21:44 2017
>> @@ -6,7 +6,8 @@ int f();
>>
>>  namespace {
>>    // CHECK-1: @_ZN12_GLOBAL__N_11bE = internal global i32 0
>> -  // CHECK-1: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0
>> +  // CHECK-1: @_ZN12_GLOBAL__N_11cE = internal global i32 0
>> +  // CHECK-1: @_ZN12_GLOBAL__N_12c2E = internal global i32 0
>>    // CHECK-1: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0
>>    // CHECK-1: @_ZN12_GLOBAL__N_11aE = internal global i32 0
>>    int a = 0;
>> @@ -15,6 +16,12 @@ namespace {
>>
>>    static int c = f();
>>
>> +  // Note, we can't use an 'L' mangling for c or c2 (like GCC does)
>> based on
>> +  // the 'static' specifier, because the variable can be redeclared
>> without it.
>> +  extern int c2;
>> +  int g() { return c2; }
>> +  static int c2 = f();
>> +
>>    class D {
>>      static int d;
>>    };
>>
>> Modified: cfe/trunk/test/SemaCXX/linkage2.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/
>> linkage2.cpp?rev=314037&r1=314036&r2=314037&view=diff
>> ============================================================
>> ==================
>> --- cfe/trunk/test/SemaCXX/linkage2.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/linkage2.cpp Fri Sep 22 15:21:44 2017
>> @@ -143,9 +143,10 @@ namespace test13 {
>>  }
>>
>>  namespace test14 {
>> +  // Anonymous namespace implies internal linkage, so 'static' has no
>> effect.
>>    namespace {
>> -    void a(void); // expected-note {{previous declaration is here}}
>> -    static void a(void) {} // expected-error {{static declaration of 'a'
>> follows non-static declaration}}
>> +    void a(void);
>> +    static void a(void) {}
>>    }
>>  }
>>
>>
>> Modified: cfe/trunk/test/SemaCXX/undefined-internal.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/
>> undefined-internal.cpp?rev=314037&r1=314036&r2=314037&view=diff
>> ============================================================
>> ==================
>> --- cfe/trunk/test/SemaCXX/undefined-internal.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/undefined-internal.cpp Fri Sep 22 15:21:44
>> 2017
>> @@ -187,6 +187,10 @@ namespace OverloadUse {
>>      void f();
>>      void f(int); // expected-warning {{function 'OverloadUse::(anonymous
>> namespace)::f' has internal linkage but is not defined}}
>>      void f(int, int); // expected-warning {{function
>> 'OverloadUse::(anonymous namespace)::f' has internal linkage but is not
>> defined}}
>> +#if __cplusplus < 201103L
>> +    // expected-note at -3 {{here}}
>> +    // expected-note at -3 {{here}}
>> +#endif
>>    }
>>    template<void x()> void t() { x(); }
>>    template<void x(int)> void t(int*) { x(10); }
>> @@ -194,6 +198,10 @@ namespace OverloadUse {
>>    void g(int n) {
>>      t<f>(&n); // expected-note {{used here}}
>>      t<f>(&n, &n); // expected-note {{used here}}
>> +#if __cplusplus < 201103L
>> +    // expected-warning at -3 {{non-type template argument referring to
>> function 'f' with internal linkage}}
>> +    // expected-warning at -3 {{non-type template argument referring to
>> function 'f' with internal linkage}}
>> +#endif
>>    }
>>  }
>>
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170922/8001914b/attachment-0001.html>


More information about the cfe-commits mailing list