| Issue |
108962
|
| Summary |
[clang-cl] Self instantiation does not work in a constant _expression_
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
VladimirShchigolev
|
Consider the following example:
```
template <int I = 0>
struct S {
static constexpr int A = I;
static constexpr int B = S<>::A;
};
static_assert(S<1>::B == 0, "S<1>::B should be 0");
```
Latest MSVC (14.41) is able to compile this:
```
C:\test>cl.exe /c example.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.41.34120 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
example.cpp
```
However clang-cl fails to compile:
```
C:\test>clang-cl.exe example.cpp
C:\test\example.cpp(4,30): error: implicit instantiation of
template 'S<>' within its own definition
4 | static constexpr int B = S<>::A;
| ^
C:\test\example.cpp(4,26): error: constexpr variable 'B' must
be initialized by a constant _expression_
4 | static constexpr int B = S<>::A;
| ^
| = 0
2 errors generated.
```
Here is a *draft* patch that I tried to make while working at #47033. It __does not__ work - it removes the errors, but the assert fails. Maybe it will help.
```
Parent: 520ddf22b2270dc092dbdbd391b1c02c403b475a ([TableGen] Remove duplicate code in applyMnemonicAliases when target uses DefaultAsmParserVariant. (#108494))
------------------------- clang/lib/Sema/SemaDecl.cpp -------------------------
index 3c6a0dff798f..6a12ed82894d 100644
@@ -352,7 +352,26 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
return nullptr;
}
- if (!LookupCtx->isDependentContext() &&
+ CXXRecordDecl *DeclFromScope = nullptr, *DeclFromScopeSpec = nullptr;
+ if (S->getLookupEntity())
+ DeclFromScope = dyn_cast_or_null<CXXRecordDecl>(S->getLookupEntity());
+
+ if (SS->isValid()) {
+ auto ClassTemplateSpecDecl =
+ dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ SS->getScopeRep()->getAsRecordDecl());
+ if (ClassTemplateSpecDecl &&
+ ClassTemplateSpecDecl->getSpecializedTemplate()) {
+ DeclFromScopeSpec = ClassTemplateSpecDecl->
+ getSpecializedTemplate()->getTemplatedDecl();
+ }
+ }
+
+ if (getLangOpts().MSVCCompat && DeclFromScope &&
+ DeclFromScope == DeclFromScopeSpec) {
+ LookupCtx = nullptr;
+ SS = nullptr;
+ } else if (!LookupCtx->isDependentContext() &&
RequireCompleteDeclContext(*SS, LookupCtx))
return nullptr;
}
------------------------ clang/lib/Sema/SemaLookup.cpp ------------------------
index d3d4bf27ae72..de7b7fbba9b3 100644
@@ -2695,6 +2695,25 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
ObjectType->castAs<TagType>()->isBeingDefined()) &&
"Caller should have completed object type");
} else if (SS && SS->isNotEmpty()) {
+ CXXRecordDecl *DeclFromScope = nullptr, *DeclFromScopeSpec = nullptr;
+ if (S->getLookupEntity())
+ DeclFromScope = dyn_cast_or_null<CXXRecordDecl>(S->getLookupEntity());
+
+ if (SS->isValid()) {
+ auto ClassTemplateSpecDecl =
+ dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ SS->getScopeRep()->getAsRecordDecl());
+ if (ClassTemplateSpecDecl &&
+ ClassTemplateSpecDecl->getSpecializedTemplate()) {
+ DeclFromScopeSpec = ClassTemplateSpecDecl->
+ getSpecializedTemplate()->getTemplatedDecl();
+ }
+ }
+
+ if (getLangOpts().MSVCCompat && DeclFromScope &&
+ DeclFromScope == DeclFromScopeSpec)
+ return LookupName(R, S, AllowBuiltinCreation);
+
// This nested-name-specifier occurs after another nested-name-specifier,
// so long into the context associated with the prior nested-name-specifier.
if ((DC = computeDeclContext(*SS, EnteringContext))) {
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs