Microsoft allows the support of ‘constexpr’ with ‘declspec(dllimport) starting
from VS2017 15.u update 4. See Constexpr doesn't support declspec(dllimport)
in VS2017 15.8 - Visual Studio Feedback.
Let’s consider this example.
lib.cpp: 
declspec(dllexport) int val=12;
declspec(dllexport)
int next(int n)
{
return n + 1;
}
app1.cpp: 
#include <iostream>
extern int __declspec(dllimport) next(int n);
int main () {
extern int __declspec(dllimport) val; constexpr int& val_ref = val; int i = next(val_ref); std::cout << "i: " << i << std::endl; return i;
}
Compiling this will give the expected output. 
 $ cl /LD lib.cpp
 $ cl /EHsc app1.cpp /link lib.lib
 $ ./app1.exe
 i: 13
The Intel compiler has the same behavior than MSVC.
Clang compiles this test case with this error:
error: constexpr variable 'val_ref' must be initialized by a constant
    expression
constexpr int& val_ref = val;
               ^         ~~~1 error generated.
I think this should be fixed. This patch is doing that.
Now let’s look now at this example (dllimport at TU scope level):
app2.cpp: 
#include <iostream>
extern int declspec(dllimport) next(int n);
extern int declspec(dllimport) val;
constexpr int& val_ref = val;
int main () {
int i = next(val_ref); std::cout << "i: " << i << std::endl; return i;
}
Compiling this will result into an unresolved symbol: 
 $ cl /EHsc app2.cpp /link lib.lib
 app2.obj : error LNK2001: unresolved external symbol "int val" (?val@@3HA)
 app2.exe : fatal error LNK1120: 1 unresolved externals
ICL and clang generate the same error.
These are the symols generated for all 3 compilers:
ICL:
003 00000000 UNDEF  notype       External     | imp_?next@@YAHH@Z (declspec(dllimport) int cdecl next(int))
004 00000000 UNDEF  notype       External     | imp_?val@@3HA (declspec(dllimport) int val)
00C 00000000 SECT4  notype       External     | ?val_ref@@3AEAHEA (int & val_ref)
00D 00000000 UNDEF  notype       External     | ?val@@3HA (int val)
MSVC:
00A 00000000 UNDEF  notype       External     | imp_?next@@YAHH@Z (declspec(dllimport) int cdecl next(int))
015 00000000 SECT6  notype       Static       | ?val_ref@@3AEAHEA (int & val_ref)
The symbols generated by ICL seem to be what's expected. MSVC should be generating an "__imp_?val" symbol.
Clang with the change in this patch is generating the expected symbols:
010 00000000 UNDEF  notype       External     | imp_?val@@3HA (declspec(dllimport) int val)
011 00000000 UNDEF  notype       External     | imp_?next@@YAHH@Z (declspec(dllimport) int __cdecl next(int))
012 00000000 SECT5  notype       External     | ?val_ref@@3AEAHEA (int & val_ref)
013 00000000 UNDEF  notype       External     | ?val@@3HA (int val)
Fixes issue https://github.com/llvm/llvm-project/issues/53182
Differential Revision: https://reviews.llvm.org/D137107
Missing code to emit this warning?