+2020-04-13 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/94426 lambdas with internal linkage are different to no-linkage
+ * decl2.c (determine_visibility): A lambda's visibility is
+ affected by its extra scope.
+ * pt.c (instantiate_decl): Determine var's visibility before
+ instantiating its initializer.
+ * tree.c (no_linkage_check): Revert code looking at visibility of
+ lambda's extra scope.
+`
2020-04-10 Iain Sandoe <iain@sandoe.co.uk>
PR c++/94528
else if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
template_decl = decl;
+ if (TREE_CODE (decl) == TYPE_DECL
+ && LAMBDA_TYPE_P (TREE_TYPE (decl))
+ && CLASSTYPE_LAMBDA_EXPR (TREE_TYPE (decl)) != error_mark_node)
+ if (tree extra = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl)))
+ {
+ /* The lambda's visibility is limited by that of its extra
+ scope. */
+ int vis = 0;
+ if (TYPE_P (extra))
+ vis = type_visibility (extra);
+ else
+ vis = expr_visibility (extra);
+ constrain_visibility (decl, vis, false);
+ }
+
/* If DECL is a member of a class, visibility specifiers on the
class can influence the visibility of the DECL. */
tree class_type = NULL_TREE;
c_inhibit_evaluation_warnings = 0;
}
+ if (VAR_P (d))
+ {
+ /* The variable might be a lambda's extra scope, and that
+ lambda's visibility depends on D's. */
+ maybe_commonize_var (d);
+ determine_visibility (d);
+ }
+
/* Mark D as instantiated so that recursive calls to
instantiate_decl do not try to instantiate it again. */
DECL_TEMPLATE_INSTANTIATED (d) = 1;
cp_walk_tree (&t, verify_stmt_tree_r, &statements, NULL);
}
-/* Check if the type T depends on a type with no linkage and if so, return
- it. If RELAXED_P then do not consider a class type declared within
- a vague-linkage function to have no linkage. */
+/* Check if the type T depends on a type with no linkage and if so,
+ return it. If RELAXED_P then do not consider a class type declared
+ within a vague-linkage function to have no linkage. Remember:
+ no-linkage is not the same as internal-linkage*/
tree
no_linkage_check (tree t, bool relaxed_p)
tree extra = LAMBDA_TYPE_EXTRA_SCOPE (t);
if (!extra)
return t;
-
- /* If the mangling scope is internal-linkage or not repeatable
- elsewhere, the lambda effectively has no linkage. (Sadly
- we're not very careful with the linkages of types.) */
- if (TREE_CODE (extra) == VAR_DECL
- && !(TREE_PUBLIC (extra)
- && (processing_template_decl
- || (DECL_LANG_SPECIFIC (extra) && DECL_USE_TEMPLATE (extra))
- /* DECL_COMDAT is set too late for us to check. */
- || DECL_VAR_DECLARED_INLINE_P (extra))))
- return t;
}
/* Otherwise there's no point in checking linkage on template functions; we
+2020-04-13 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/94426
+ * g++.dg/cpp0x/lambda/pr94426-[12].C: New.
+ * g++.dg/abi/lambda-vis.C: Drop a warning.
+ * g++.dg/cpp0x/lambda/lambda-mangle.C: Lambda visibility on
+ variable changes.
+ * g++.dg/opt/dump1.C: Drop warnings of no import.
+
2020-04-13 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* gcc.target/msp430/operand-modifiers.c: New test.
// { dg-options "-fno-inline" }
template<typename T> int sfoo (T); // { dg-warning "used but never defined" }
-template<typename T> int gfoo (T); // { dg-warning "used but never defined" }
+template<typename T> int gfoo (T); // OK, but not completable
template<typename T> int ifoo (T); // OK
template<typename T> struct Wrapper {};
template<typename T> Wrapper<T> capture (T &&) {return Wrapper<T> ();}
[]{}();
}
-// lambdas used in non-template, non-class body initializers are internal.
+// lambdas used in namespace-scope initializers have the linkage of
+// the decl
// { dg-final { scan-assembler-not "weak\[^\n\r\]*_ZNKUlv" } }
-// { dg-final { scan-assembler-not "weak\[^\n\r\]*variable" } }
+// { dg-final { scan-assembler "weak\[^\n\r\]*variableMUlvE_clEv" { target c++14_down } } }
+// in c++17 and up, this operator() become constexpr, no not emitted
+// { dg-final { scan-assembler-not "weak\[^\n\r\]*variableMUlvE_clEv" { target c++17 } } }
int variable = []{return 1;}();
// And a template instantiated with such a lambda is also internal.
--- /dev/null
+// { dg-do compile { target c++14 } }
+// PR 94426 ICE mangling lambda
+// { dg-options {-flto -O2} }
+
+template <bool> using Void = void;
+
+template <typename U> bool Init (U) {return true;}
+template <typename> bool VAR = Init ([] {});
+
+template <typename T>
+Void<false && VAR<T>> Foo (T)
+{}
+
+void q ()
+{
+ Foo ([] {});
+}
--- /dev/null
+// { dg-do compile { target c++14 } }
+// PR 94426 ICE mangling lambda
+
+template <bool> using Void = void;
+
+template <typename U> bool Init (U) {return true;}
+template <typename> bool VAR = Init ([] {});
+
+template <typename T>
+Void<false && VAR<T>> Foo (T)
+{}
+
+void q ()
+{
+ Foo ([] {});
+}
+
+// The instantiation of VAR becomes local
+// { dg-final { scan-assembler {.local _Z3VARIZ1qvEUlvE_E} { target { i?86-*-* x86_64-*-* } } } }
+// { dg-final { scan-assembler {.comm _Z3VARIZ1qvEUlvE_E,1,1} { target { i?86-*-* x86_64-*-* } } } }
typename __add_ref<
typename tuple_element<__i, tuple<_Elements...>>::type
>::type
- get(tuple<_Elements...>& __t) noexcept; // { dg-warning "used but never defined" }
+ get(tuple<_Elements...>& __t) noexcept;
template<std::size_t... _Indexes>
struct _Index_tuple
{};
};
template<typename _Callable, typename... _Args>
typename _Bind_simple_helper<_Callable, _Args...>::__type
- __bind_simple(_Callable&& __callable, _Args&&... __args) // { dg-warning "used but never defined" }
+ __bind_simple(_Callable&& __callable, _Args&&... __args)
;
union _Any_data
;
{
protected:
static _Functor*
- _M_get_pointer(const _Any_data& __source) // { dg-warning "used but never defined" }
+ _M_get_pointer(const _Any_data& __source)
;
};
};
_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
static pointer
- allocate(_Alloc& __a, size_type __n) // { dg-warning "used but never defined" }
+ allocate(_Alloc& __a, size_type __n)
;
template<typename _Tp, typename... _Args>
static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)