diff --git a/docs/userguide/documentation/linker_script.md b/docs/userguide/documentation/linker_script.md index 30575b5033..b1fec53dfb 100644 --- a/docs/userguide/documentation/linker_script.md +++ b/docs/userguide/documentation/linker_script.md @@ -1581,6 +1581,11 @@ A version script is a sequence of *version nodes*. Each node has an optional name and contains `global:` and/or `local:` blocks. Each block lists symbol patterns terminated by `;`. +:::{note} +It is an error for a ``local:`` block to appear before a ``global:`` block in +the same version node. +::: + ``` /* Anonymous (unnamed) version node. */ { diff --git a/lib/ScriptParser/ScriptParser.cpp b/lib/ScriptParser/ScriptParser.cpp index f62aa9b388..9e314bc9b1 100644 --- a/lib/ScriptParser/ScriptParser.cpp +++ b/lib/ScriptParser/ScriptParser.cpp @@ -1568,6 +1568,10 @@ void ScriptParser::readVersionSymbols(VersionScriptNode &VSN) { continue; } if (Tok == "global:" || (Tok == "global" && consume(":"))) { + if (VSN.getLocalBlock()) { + setError("global scope must appear before local scope", Tok); + return; + } VSN.switchToGlobal(); continue; } diff --git a/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/GlobalAfterLocal.test b/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/GlobalAfterLocal.test new file mode 100644 index 0000000000..b0477e7fa8 --- /dev/null +++ b/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/GlobalAfterLocal.test @@ -0,0 +1,15 @@ +#---GlobalAfterLocal.test------------ SharedLib,VersionScript ----------------# +#BEGIN_COMMENT +# This test verifies that version-script diagnostics point at a global block +# that appears after a local block. +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -o %t1.o -c %p/Inputs/1.c -fPIC +RUN: %not %link %linkopts -o %t1.so %t1.o -shared \ +RUN: --version-script %p/Inputs/vs.t 2>&1 \ +RUN: | %filecheck %s --strict-whitespace --match-full-lines +#END_TEST + +CHECK:Error: {{.*}}vs.t:4:3: global scope must appear before local scope{{.*}} +CHECK-NEXT:>>> global: +CHECK-NEXT:>>> ^ diff --git a/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/Inputs/1.c b/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/Inputs/1.c new file mode 100644 index 0000000000..9fe07f82f9 --- /dev/null +++ b/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/Inputs/1.c @@ -0,0 +1 @@ +int foo() { return 0; } diff --git a/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/Inputs/vs.t b/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/Inputs/vs.t new file mode 100644 index 0000000000..49a82efee2 --- /dev/null +++ b/test/Common/standalone/VersionScriptDiagnostics/GlobalAfterLocal/Inputs/vs.t @@ -0,0 +1,6 @@ +V1 { + local: + *; + global: + foo; +};