Skip to content

Commit

Permalink
Revert "Recommit "[Driver] Default to -fno-common for all targets""
Browse files Browse the repository at this point in the history
This reverts commit 2c36c23.

Still problems in the test-suite, which I really thought I had fixed...
  • Loading branch information
Sjoerd Meijer committed Mar 9, 2020
1 parent 25f2639 commit f35d112
Show file tree
Hide file tree
Showing 57 changed files with 152 additions and 164 deletions.
4 changes: 0 additions & 4 deletions clang/docs/ClangCommandLineReference.rst
Expand Up @@ -1307,10 +1307,6 @@ Use colors in diagnostics

.. option:: -fcommon, -fno-common

Place definitions of variables with no storage class and no initializer
(tentative definitions) in a common block, instead of generating individual
zero-initialized definitions (default -fno-common).

.. option:: -fcompile-resource=<arg>, --resource <arg>, --resource=<arg>

.. option:: -fconstant-cfstrings, -fno-constant-cfstrings
Expand Down
7 changes: 0 additions & 7 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -84,13 +84,6 @@ future versions of Clang.
Modified Compiler Flags
-----------------------

- -fno-common has been enabled as the default for all targets. Therefore, C
code that uses tentative definitions as definitions of a variable in multiple
translation units will trigger multiple-definition linker errors. Generally,
this occurs when the use of the ``extern`` keyword is neglected in the declaration
of a variable in a header file. In some cases, no specific translation unit
provides a definition of the variable. The previous behavior can be restored by
specifying ``-fcommon``.

New Pragmas in Clang
--------------------
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -848,8 +848,7 @@ def fno_record_command_line : Flag<["-"], "fno-record-command-line">,
Group<f_clang_Group>;
def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>;
def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>;
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>,
Flags<[CoreOption, CC1Option]>, HelpText<"Place uninitialized global variables in a common block">;
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>;
def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>;
def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group<f_clang_Group>,
Flags<[CoreOption, CC1Option]>,
Expand Down
22 changes: 19 additions & 3 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -1408,6 +1408,20 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
}
}

static bool isNoCommonDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
default:
if (Triple.isOSFuchsia())
return true;
return false;

case llvm::Triple::xcore:
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
return true;
}
}

static bool hasMultipleInvocations(const llvm::Triple &Triple,
const ArgList &Args) {
// Supported only on Darwin where we invoke the compiler multiple times
Expand Down Expand Up @@ -5678,9 +5692,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(options::OPT_Qy, options::OPT_Qn, true))
CmdArgs.push_back("-Qn");

// -fno-common is the default, set -fcommon only when that flag is set.
if (Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common, false))
CmdArgs.push_back("-fcommon");
// -fcommon is the default unless compiling kernel code or the target says so
bool NoCommonDefault = KernelOrKext || isNoCommonDefault(RawTriple);
if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common,
!NoCommonDefault))
CmdArgs.push_back("-fno-common");

// -fsigned-bitfields is default, and clang doesn't yet support
// -funsigned-bitfields.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -809,7 +809,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.RecordCommandLine =
std::string(Args.getLastArgValue(OPT_record_command_line));
Opts.MergeAllConstants = Args.hasArg(OPT_fmerge_all_constants);
Opts.NoCommon = !Args.hasArg(OPT_fcommon);
Opts.NoCommon = Args.hasArg(OPT_fno_common);
Opts.NoInlineLineTables = Args.hasArg(OPT_gno_inline_line_tables);
Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
Opts.OptimizeSize = getOptimizationLevelSize(Args);
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/2008-07-21-mixed-var-fn-decl.c
Expand Up @@ -3,6 +3,6 @@
int g0, f0();
int f1(), g1;

// CHECK: @g0 = {{(dso_local )?}}global i32 0, align 4
// CHECK: @g1 = {{(dso_local )?}}global i32 0, align 4
// CHECK: @g0 = common {{(dso_local )?}}global i32 0, align 4
// CHECK: @g1 = common {{(dso_local )?}}global i32 0, align 4

4 changes: 2 additions & 2 deletions clang/test/CodeGen/2009-10-20-GlobalDebug.c
Expand Up @@ -2,10 +2,10 @@
// RUN: %clang -target i386-apple-darwin10 -flto -S -g %s -o - | FileCheck %s

// CHECK: @main.localstatic = internal global i32 0, align 4, !dbg [[L:![0-9]+]]
// CHECK: @global = global i32 0, align 4, !dbg [[G:![0-9]+]]
// CHECK: @global = common global i32 0, align 4, !dbg [[G:![0-9]+]]

int global;
int main() {
int main() {
static int localstatic;
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/aarch64-sve.c
Expand Up @@ -16,7 +16,7 @@
// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVFloat64_t'
// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVBool_t'

// CHECK: @ptr = global <vscale x 16 x i8>* null, align 8
// CHECK: @ptr = common global <vscale x 16 x i8>* null, align 8
// CHECK: %s8 = alloca <vscale x 16 x i8>, align 16
// CHECK: %s16 = alloca <vscale x 8 x i16>, align 16
// CHECK: %s32 = alloca <vscale x 4 x i32>, align 16
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGen/address-space.c
@@ -1,13 +1,13 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -enable-var-scope -check-prefixes=CHECK,X86 %s
// RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -enable-var-scope -check-prefixes=CHECK,AMDGCN %s

// CHECK: @foo = addrspace(1) global
// CHECK: @foo = common addrspace(1) global
int foo __attribute__((address_space(1)));

// CHECK: @ban = addrspace(1) global
// CHECK: @ban = common addrspace(1) global
int ban[10] __attribute__((address_space(1)));

// CHECK: @a = global
// CHECK: @a = common global
int a __attribute__((address_space(0)));

// CHECK-LABEL: define i32 @test1()
Expand Down
9 changes: 2 additions & 7 deletions clang/test/CodeGen/alias.c
Expand Up @@ -5,13 +5,8 @@
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECKGLOBALS %s

int g0;
// CHECKBASIC-DAG: @g0 = global i32 0
// CHECKASM-DAG: .bss
// CHECKASM-DAG: .globl g0
// CHECKASM-DAG: .p2align 2
// CHECKASM-DAG: g0:
// CHECKASM-DAG: .long 0
// CHECKASM-DAG: .size g0, 4
// CHECKBASIC-DAG: @g0 = common global i32 0
// CHECKASM-DAG: .comm g0,4,4
__thread int TL_WITH_ALIAS;
// CHECKBASIC-DAG: @TL_WITH_ALIAS = thread_local global i32 0, align 4
// CHECKASM-DAG: .globl TL_WITH_ALIAS
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/align-systemz.c
Expand Up @@ -7,10 +7,10 @@ struct test {
};

char c;
// CHECK-DAG: @c = global i8 0, align 2
// CHECK-DAG: @c = common global i8 0, align 2

struct test s;
// CHECK-DAG: @s = global %struct.test zeroinitializer, align 2
// CHECK-DAG: @s = common global %struct.test zeroinitializer, align 2

extern char ec;
// CHECK-DAG: @ec = external global i8, align 2
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/alignment.c
Expand Up @@ -7,7 +7,7 @@ union {int a[4]; __attribute((aligned(16))) float b[4];} b;
// CHECK: @b = {{.*}}zeroinitializer, align 16

long long int test5[1024];
// CHECK-DAG: @test5 = global [1024 x i64] zeroinitializer, align 8
// CHECK-DAG: @test5 = common global [1024 x i64] zeroinitializer, align 8

// PR5279 - Reduced alignment on typedef.
typedef int myint __attribute__((aligned(1)));
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/asm-label.c
Expand Up @@ -11,9 +11,9 @@ int *test(void) {
}

// LINUX: @bar = internal global i32 0
// LINUX: @foo = global i32 0
// LINUX: @foo = common global i32 0
// LINUX: declare i8* @alias(i32)

// DARWIN: @"\01bar" = internal global i32 0
// DARWIN: @"\01foo" = global i32 0
// DARWIN: @"\01foo" = common global i32 0
// DARWIN: declare i8* @"\01alias"(i32)
2 changes: 1 addition & 1 deletion clang/test/CodeGen/attr-weak-import.c
Expand Up @@ -20,7 +20,7 @@ extern int E __attribute__((weak_import));

// CHECK: @A = global i32
// CHECK-NOT: @B =
// CHECK: @C = global i32
// CHECK: @C = common global i32
// CHECK: @D = global i32
// CHECK: @E = global i32

4 changes: 2 additions & 2 deletions clang/test/CodeGen/attr-weakref2.c
Expand Up @@ -8,7 +8,7 @@ int test1_h(void) {
return test1_g;
}

// CHECK: @test2_f = global i32 0, align 4
// CHECK: @test2_f = common global i32 0, align 4
int test2_f;
static int test2_g __attribute__((weakref("test2_f")));
int test2_h(void) {
Expand All @@ -25,7 +25,7 @@ int test3_h(void) {
return test3_g;
}

// CHECK: @test4_f = global i32 0, align 4
// CHECK: @test4_f = common global i32 0, align 4
extern int test4_f;
static int test4_g __attribute__((weakref("test4_f")));
int test4_h(void) {
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/attributes.c
Expand Up @@ -20,7 +20,7 @@ int t18 = 1;
// CHECK: @t16 = extern_weak global i32
extern int t16 __attribute__((weak_import));

// CHECK: @t6 = protected global i32 0
// CHECK: @t6 = common protected global i32 0
int t6 __attribute__((visibility("protected")));

// CHECK: @t12 = global i32 0, section "SECT"
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/blocks-windows.c
Expand Up @@ -68,7 +68,7 @@ int (*g(void))(void) {
}

// CHECK-BLOCKS-IN-BLOCKS-DECL: @_NSConcreteStackBlock = external dso_local dllexport global i8*
// CHECK-BLOCKS-IN-BLOCKS-DEFN: @_NSConcreteStackBlock = dso_local dllexport global [5 x i32]
// CHECK-BLOCKS-IN-BLOCKS-DEFN: @_NSConcreteStackBlock = common dso_local dllexport global [5 x i32]
// CHECK-BLOCKS-NOT-IN-BLOCKS: @_NSConcreteStackBlock = external dllimport global i8*
// CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN: @_NSConcreteStackBlock = external dllimport global i8*
// CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN-DLLIMPORT: @_NSConcreteStackBlock = external dllimport global i8*
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/bool-convert.c
Expand Up @@ -2,16 +2,16 @@
// All of these should uses the memory representation of _Bool

// CHECK-LABEL: %struct.teststruct1 = type { i8, i8 }
// CHECK-LABEL: @test1 = global %struct.teststruct1
// CHECK-LABEL: @test1 = common global %struct.teststruct1
struct teststruct1 {_Bool a, b;} test1;

// CHECK-LABEL: @test2 = global i8* null
// CHECK-LABEL: @test2 = common global i8* null
_Bool* test2;

// CHECK-LABEL: @test3 = global [10 x i8]
// CHECK-LABEL: @test3 = common global [10 x i8]
_Bool test3[10];

// CHECK-LABEL: @test4 = global [0 x i8]* null
// CHECK-LABEL: @test4 = common global [0 x i8]* null
_Bool (*test4)[];

// CHECK-LABEL: define void @f(i32 %x)
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/c11atomics.c
Expand Up @@ -25,7 +25,7 @@ struct elem {
// CHECK-DAG: %struct.elem = type { %struct.ptr }

struct ptr object;
// CHECK-DAG: @object = global %struct.ptr zeroinitializer
// CHECK-DAG: @object = common global %struct.ptr zeroinitializer

// CHECK-DAG: @testStructGlobal = global {{.*}} { i16 1, i16 2, i16 3, i16 4 }
// CHECK-DAG: @testPromotedStructGlobal = global {{.*}} { %{{.*}} { i16 1, i16 2, i16 3 }, [2 x i8] zeroinitializer }
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/cfstring-elf-cfbuild-x86_64.c
Expand Up @@ -30,7 +30,7 @@ const CFStringRef string = (CFStringRef)__builtin___CFStringMakeConstantString("


// CHECK-CF-IN-CF-DECL: @__CFConstantStringClassReference = external global [0 x i32]
// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = global [32 x i64] zeroinitializer, align 16
// CHECK-CF: @__CFConstantStringClassReference = global [1 x i64] zeroinitializer, align 8
// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = common global [32 x i64] zeroinitializer, align 16
// CHECK-CF: @__CFConstantStringClassReference = common global [1 x i64] zeroinitializer, align 8
// CHECK-CF-EXTERN: @__CFConstantStringClassReference = external global [0 x i32]
// CHECK-CF-EXTERN: @.str = private unnamed_addr constant [7 x i8] c"string\00", section ".rodata", align 1
2 changes: 1 addition & 1 deletion clang/test/CodeGen/cfstring-windows.c
Expand Up @@ -32,7 +32,7 @@ typedef struct __CFString *CFStringRef;
const CFStringRef string = (CFStringRef)__builtin___CFStringMakeConstantString("string");

// CHECK-CF-IN-CF-DECL: @__CFConstantStringClassReference = external dso_local dllexport global [0 x i32]
// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = dso_local dllexport global [32 x i32]
// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = common dso_local dllexport global [32 x i32]
// CHECK-CF: @__CFConstantStringClassReference = external dllimport global [0 x i32]
// CHECK-CF-EXTERN: @__CFConstantStringClassReference = external dllimport global [0 x i32]
// CHECK-CF-EXTERN-DLLIMPORT: @__CFConstantStringClassReference = external dllimport global [0 x i32]
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/default-address-space.c
@@ -1,13 +1,13 @@
// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHECK,COM %s

// CHECK-DAG: @foo = addrspace(1) global i32 0
// CHECK-DAG: @foo = common addrspace(1) global i32 0
int foo;

// CHECK-DAG: @ban = addrspace(1) global [10 x i32] zeroinitializer
// CHECK-DAG: @ban = common addrspace(1) global [10 x i32] zeroinitializer
int ban[10];

// CHECK-DAG: @A = addrspace(1) global i32* null
// CHECK-DAG: @B = addrspace(1) global i32* null
// CHECK-DAG: @A = common addrspace(1) global i32* null
// CHECK-DAG: @B = common addrspace(1) global i32* null
int *A;
int *B;

Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/dllexport-1.c
Expand Up @@ -9,8 +9,8 @@
// CHECK-MSVC: @z = dso_local constant i32 4, align 4
// CHECK-LNX: @z = constant i32 4, align 4

// CHECK-MSVC: @y = dso_local dllexport constant i32 0, align 4
// CHECK-LNX: @y = constant i32 0, align 4
// CHECK-MSVC: @y = common dso_local dllexport global i32 0, align 4
// CHECK-LNX: @y = common global i32 0, align 4

__declspec(dllexport) int const x = 3;
__declspec(dllexport) const int y;
Expand Down
18 changes: 9 additions & 9 deletions clang/test/CodeGen/dllexport.c
Expand Up @@ -14,7 +14,7 @@
__declspec(dllexport) extern int ExternGlobalDecl;

// dllexport implies a definition.
// CHECK-DAG: @GlobalDef = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @GlobalDef = common dso_local dllexport global i32 0, align 4
__declspec(dllexport) int GlobalDef;

// Export definition.
Expand All @@ -27,11 +27,11 @@ __declspec(dllexport) extern int GlobalDeclInit;
int GlobalDeclInit = 1;

// Redeclarations
// CHECK-DAG: @GlobalRedecl1 = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @GlobalRedecl1 = common dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int GlobalRedecl1;
__declspec(dllexport) int GlobalRedecl1;

// CHECK-DAG: @GlobalRedecl2 = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @GlobalRedecl2 = common dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int GlobalRedecl2;
int GlobalRedecl2;

Expand Down Expand Up @@ -70,29 +70,29 @@ __declspec(dllexport) void redecl2(void);
//===----------------------------------------------------------------------===//

// dllexport takes precedence over the dllimport if both are specified.
// CHECK-DAG: @PrecedenceGlobal1A = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @PrecedenceGlobal1B = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @PrecedenceGlobal1A = common dso_local dllexport global i32 0, align 4
// CHECK-DAG: @PrecedenceGlobal1B = common dso_local dllexport global i32 0, align 4
__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A;
__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B;

// CHECK-DAG: @PrecedenceGlobal2A = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @PrecedenceGlobal2B = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @PrecedenceGlobal2A = common dso_local dllexport global i32 0, align 4
// CHECK-DAG: @PrecedenceGlobal2B = common dso_local dllexport global i32 0, align 4
__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A;
__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B;

// CHECK-DAG: @PrecedenceGlobalRedecl1 = dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int PrecedenceGlobalRedecl1;
__declspec(dllimport) int PrecedenceGlobalRedecl1 = 0;

// CHECK-DAG: @PrecedenceGlobalRedecl2 = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @PrecedenceGlobalRedecl2 = common dso_local dllexport global i32 0, align 4
__declspec(dllimport) extern int PrecedenceGlobalRedecl2;
__declspec(dllexport) int PrecedenceGlobalRedecl2;

// CHECK-DAG: @PrecedenceGlobalMixed1 = dso_local dllexport global i32 1, align 4
__attribute__((dllexport)) extern int PrecedenceGlobalMixed1;
__declspec(dllimport) int PrecedenceGlobalMixed1 = 1;

// CHECK-DAG: @PrecedenceGlobalMixed2 = dso_local dllexport global i32 0, align 4
// CHECK-DAG: @PrecedenceGlobalMixed2 = common dso_local dllexport global i32 0, align 4
__attribute__((dllimport)) extern int PrecedenceGlobalMixed2;
__declspec(dllexport) int PrecedenceGlobalMixed2;

Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/dllimport.c
Expand Up @@ -46,8 +46,8 @@ __declspec(dllimport) extern int GlobalRedecl3;
USEVAR(GlobalRedecl3)

// Make sure this works even if the decl has been used before it's defined (PR20792).
// MS: @GlobalRedecl4 = dso_local dllexport global i32
// GNU: @GlobalRedecl4 = dso_local global i32
// MS: @GlobalRedecl4 = common dso_local dllexport global i32
// GNU: @GlobalRedecl4 = common dso_local global i32
__declspec(dllimport) extern int GlobalRedecl4;
USEVAR(GlobalRedecl4)
int GlobalRedecl4; // dllimport ignored
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/microsoft-no-common-align.c
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fcommon -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -o - %s | FileCheck %s
typedef float TooLargeAlignment __attribute__((__vector_size__(64)));
typedef float NormalAlignment __attribute__((__vector_size__(4)));

Expand Down
11 changes: 5 additions & 6 deletions clang/test/CodeGen/no-common.c
@@ -1,16 +1,15 @@
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-DEFAULT
// RUN: %clang_cc1 %s -fno-common -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-DEFAULT
// RUN: %clang_cc1 %s -fcommon -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-COMMON
// RUN: %clang_cc1 %s -fno-common -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-NOCOMMON

// CHECK-COMMON: @x = common {{(dso_local )?}}global
// CHECK-DEFAULT: @x = {{(dso_local )?}}global
// CHECK-DEFAULT: @x = common {{(dso_local )?}}global
// CHECK-NOCOMMON: @x = {{(dso_local )?}}global
int x;

// CHECK-COMMON: @ABC = {{(dso_local )?}}global
// CHECK-DEFAULT: @ABC = {{(dso_local )?}}global
// CHECK-NOCOMMON: @ABC = {{(dso_local )?}}global
typedef void* (*fn_t)(long a, long b, char *f, int c);
fn_t ABC __attribute__ ((nocommon));

// CHECK-COMMON: @y = common {{(dso_local )?}}global
// CHECK-DEFAULT: @y = common {{(dso_local )?}}global
// CHECK-NOCOMMON: @y = common {{(dso_local )?}}global
int y __attribute__((common));

0 comments on commit f35d112

Please sign in to comment.