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

Reply via email to